4

我想这个网站上的大多数人都会同意可以通过两种方式外包实施:

  • 私有继承
  • 作品

继承权最常被滥用。值得注意的是,当另一种形式或继承可能更好时,通常使用公共继承,并且通常应该使用组合而不是私有继承。

当然,通常的警告适用,但我想不出任何时候我真的需要继承来解决实现问题。

然而,对于Boost Parameter 库,您会注意到他们选择继承而不是组合来实现命名参数习惯用法(对于构造函数)。

我只能想到经典的 EBO(空基优化)解释,因为这里没有我可以看到的虚拟方法。

有谁知道更好或可以将我重定向到讨论?

谢谢,马修。

4

2 回答 2

2

编辑哎呀!我在下面发布了答案,因为我误读了您的帖子。我以为你说 Boost 库使用组合而不是继承,而不是相反。不过,如果它对任何人都有用...(请参阅 EDIT2 了解我认为可能是您问题的答案。)

我不知道 Boost Parameter Library 的具体答案。但是,我可以说这通常是一个更好的选择。原因是每当您可以选择以多种方式实现关系时,您应该选择最弱的一种(低耦合/高内聚)。因为继承比组合强...

请注意,有时使用私有继承也会使实现异常安全代码变得更加困难。以operator==为例。使用组合,您可以创建一个临时并使用提交/回滚逻辑进行分配(假设对象的正确构造)。但是如果你使用继承,你可能会在派生类的Base::operator==(obj)内部做一些事情。operator==如果该Base::operator==(obj)调用抛出,您将冒着保证的风险。

编辑2: 现在,试图回答你真正问的问题。这是我从您提供的链接中可以理解的。由于我不知道图书馆的所有细节,如果我错了,请纠正我。

当您将组合用于“实现方式”时,您需要为委派提供一层间接性。


struct AImpl 
{ 
  //Dummy code, just for the example.
  int get_int() const { return 10; }
};

struct A { AImpl * impl_; int get_int() const { return impl->get_int(); } /* ... */ };

在启用参数的构造函数的情况下,您需要创建一个实现类,但您仍然应该能够以透明的方式使用“包装器”类。这意味着在您提到的链接的示例中,希望您可以myclass像操作一样操作myclass_impl。这只能通过继承来完成。(请注意,在示例中,继承是公共的,因为它是 struct 的默认值。)

我假设myclass_impl它应该是“真正的”类,具有数据、行为等的类。然后,如果你有一个类似的方法get_int()并且如果你不使用继承,你将被迫只写一个包装get_int()myclass就像我上面做的那样。

于 2009-09-28T15:43:08.283 回答
0

这不是我曾经使用过的库,因此浏览您链接到的文档是我唯一以此为基础的答案。我完全有可能是错的,但是...

他们提到构造函数委托是使用公共基类的一个原因。你是对的,组合也可以解决这个特定问题。但是,将它们全部放在一个类型中是行不通的。他们希望将多个构造函数签名煮沸到一个用户编写的初始化函数中,并且不需要构造函数委托,这需要第二种数据类型。我的怀疑是,从将所有内容放入类本身的角度来看,已经编写了大部分库。当他们遇到构造函数委托问题时,他们妥协了。将其放入基类可能更接近于他们对以前的功能所做的事情,他们知道您正在使用的类可以访问该功能的接口和实现方面。

我不会以任何方式抨击图书馆。我非常怀疑我能否在任何合理的时间内组建一个像这样的图书馆。我只是在字里行间阅读。你知道,从无知中说出来,但假装我真的知道一些事情。:-)

于 2009-09-28T19:14:50.097 回答