我怎么能避免钻石继承?

时间:2016-07-08 12:43:15

标签: c++ oop inheritance

我目前正在进行C ++设计,我有这种继承结构:

  A
 / \
B   C

A执行类BC以及类BC共有的计算是两种不同的初始化方式{ {1}}。

我想添加某种混合初始化,即使用AD中的方法的类B

但是,我需要使用钻石继承才能访问CB::init()来设置C::init()的属性。

我知道我可以使用虚拟继承来避免钻石问题,但是当我手动复制方法时,我会遇到运行时错误。此外,在尝试实例化类DB时遇到问题,同事建议我不要在我的设计中使用钻石继承。

因此,我想找一些"清洁"解决方法,我无法做到。

  • 我可以将所有初始化例程放在课程C中,但目前它们很好地分开了,我想避免让一个大课堂我真的无法实现将类AB的不同功能组分开。回答后编辑:这是我选择的,使用不同的cpp文件来分割我的"大"将类分为逻辑方法组。

  • 我还可以删除继承链接并将其替换为友谊,其中CB的方法是静态的,并且处理类型为C的指针。这样,我就可以从A*拨打B::init(A* a)C::init(A* a)。但是,我必须将D::init(A* a)的所有用法替换为_fooAttribute,这有点麻烦且看起来不对。

你会推荐什么?

2 个答案:

答案 0 :(得分:3)

如果您的设计需要钻石继承,那么您需要这样做。人们把它当作C ++的“一定不能使用”的特性,但问题的真相是它存在,它是完全定义的(如果理解起来有点复杂),如果你的问题空间需要它,你应该使用它它

特别是,我无法理解这是否确实是钻石继承。特别是,mtcars2 <- tidyr::gather(mtcars) ggplot(mtcars2, aes(value)) + geom_density() + facet_wrap(~key, scales = 'free') 内的AB内的AC实例相同是否合理? }?从你的问题来看,它似乎不是。 AB都有一定的,不同的方式来初始化C。如果是这种情况,这不是钻石继承。只需确保AB在非虚拟继承中继承C

说到这一点,确保这确实是你的设计所要求的。你能诚实地说A B吗?那A?你能诚实地说C 一个D和一个B吗?如果没有,可能让C成为AB或两者的成员,或者C成员B成为C感。

如果您继承D的唯一原因是扩展A提供的方法,那么请考虑简单地将这些方法作为A的成员。如上所述,虽然减少代码重复是值得的,但设计应确保继承关系是关系。偏离这一点就是在寻找麻烦。

答案 1 :(得分:1)

继承是一个&#34;是一个&#34;关系。如果B是A,那么你很好。这同样适用于C.根据您的描述,您没有这种关系。相反,您有一个实现计算的实用程序类(A)。您可能希望使其具有静态方法,因为它本身不需要存储任何数据,如果它真的是一个实用程序。传递A或B或C的实例并让它使用B-&gt; fooAttribute访问它所需的属性没有任何问题。但是,您可能希望B和C都实现一个通用界面,因此您不必知道您正在查看哪个界面。

相关问题