C ++中的虚拟继承是防止钻石问题的有效方法。但是,我似乎无法在每个案例中使其正常工作。
这将很难解释,但我希望我会管理。让我们来解决问题:
A继承B. A是名为C的类集的基类,另一个是名为D的类。
问题在于C类的集合具有围绕B的共同特征。
我想做什么,但是不可能,是一个真正继承B的E类,它由C继承。问题是:
在这种情况下,A实际上并不继承B.所以它不起作用。
如果A实际上是继承B,那么我需要在每个D类中使用B的构造函数。
结论:在每个案例中都存在重复的代码。如果没有任何重复的代码,我怎么能摆脱这个问题?
答案 0 :(得分:1)
好的,所以你说你有:
B
+
|
v
A
+
+----+----+
v v
C D
所有这些都是非虚拟继承,然后您拥有 virtualy 继承E
的类B
,而C
也继承了它,因此完整的图表将是:
+-----------+B
| +
| |
v v
E A
+ +
+---+---+----+----+
v v
C D
B
继承了E
virtualy 的例外情况。
解决方案很简单,您应该A
也虚拟继承B
,但我从您的问题中收集到您无法修改A
。您的下一个选项是让C
继承A
或E
并拥有另一个的实例,这称为delegation.
另一种方法是,您可以提供一个通用接口并允许多态,您可能希望创建一个接口(纯虚拟类),该接口具有E
C
使用的所有功能,然后使C
和E
派生出该界面。 E
将从接口实现虚函数,C将实现它作为E
实现的函数调用。或者(不推荐)你可以忍受死亡的钻石,如果它对你没有问题,但是确定这是棘手的,我不建议这是一个可怕的想法。
答案 1 :(得分:1)
将B
拆分为接口部分IB
(抽象基类,无数据成员)和实现部分Bimpl
。 Multiply-inherit only IB
。由于IB
没有数据成员,因此不需要非默认构造函数,因此您无需在任何地方重复它。
对于因此更改而变为抽象的层次结构中的每个类C
,请创建继承自Cimpl
和C
的{{1}}。永远不要继承Bimpl
。 Cimpl
的非默认构造函数(以前为Bimpl
)仅在B
中调用。