我目前正在进行C ++设计,我有这种继承结构:
A
/ \
B C
类A
执行类B
和C
以及类B
和C
共有的计算是两种不同的初始化方式{ {1}}。
我想添加某种混合初始化,即使用A
和D
中的方法的类B
。
但是,我需要使用钻石继承才能访问C
和B::init()
来设置C::init()
的属性。
我知道我可以使用虚拟继承来避免钻石问题,但是当我手动复制方法时,我会遇到运行时错误。此外,在尝试实例化类D
和B
时遇到问题,同事建议我不要在我的设计中使用钻石继承。
因此,我想找一些"清洁"解决方法,我无法做到。
我可以将所有初始化例程放在课程C
中,但目前它们很好地分开了,我想避免让一个大课堂我真的无法实现将类A
和B
的不同功能组分开。回答后编辑:这是我选择的,使用不同的cpp文件来分割我的"大"将类分为逻辑方法组。
我还可以删除继承链接并将其替换为友谊,其中C
和B
的方法是静态的,并且处理类型为C
的指针。这样,我就可以从A*
拨打B::init(A* a)
和C::init(A* a)
。但是,我必须将D::init(A* a)
的所有用法替换为_fooAttribute
,这有点麻烦且看起来不对。
你会推荐什么?
答案 0 :(得分:3)
如果您的设计需要钻石继承,那么您需要这样做。人们把它当作C ++的“一定不能使用”的特性,但问题的真相是它存在,它是完全定义的(如果理解起来有点复杂),如果你的问题空间需要它,你应该使用它它
特别是,我无法理解这是否确实是钻石继承。特别是,mtcars2 <- tidyr::gather(mtcars)
ggplot(mtcars2, aes(value)) + geom_density() + facet_wrap(~key, scales = 'free')
内的A
和B
内的A
与C
的实例相同是否合理? }?从你的问题来看,它似乎不是。 A
和B
都有一定的,不同的方式来初始化C
。如果是这种情况,这不是钻石继承。只需确保A
和B
在非虚拟继承中继承C
。
说到这一点,确保这确实是你的设计所要求的。你能诚实地说A
是 B
吗?那A
?你能诚实地说C
是一个D
和一个B
吗?如果没有,可能让C
成为A
,B
或两者的成员,或者C
成员B
成为C
感。
如果您继承D
的唯一原因是扩展A
提供的方法,那么请考虑简单地将这些方法作为A
的成员。如上所述,虽然减少代码重复是值得的,但设计应确保继承关系是是关系。偏离这一点就是在寻找麻烦。
答案 1 :(得分:1)
继承是一个&#34;是一个&#34;关系。如果B是A,那么你很好。这同样适用于C.根据您的描述,您没有这种关系。相反,您有一个实现计算的实用程序类(A)。您可能希望使其具有静态方法,因为它本身不需要存储任何数据,如果它真的是一个实用程序。传递A或B或C的实例并让它使用B-&gt; fooAttribute访问它所需的属性没有任何问题。但是,您可能希望B和C都实现一个通用界面,因此您不必知道您正在查看哪个界面。