我怎样才能避免钻石继承
How could I avoid diamond inheritance?
我目前正在研究一个C++设计,其中我有这个继承结构:
A
/
B C
类A
执行类B
和C
共同的计算,类B
和C
是初始化A
的两种不同方式。
我想添加某种混合初始化,即一个类D
,它将使用 B
和 C
的方法。
但是,我需要使用钻石继承才能访问B::init()
,C::init()
来设置D
的属性。
我知道我可以使用虚拟继承来避免钻石问题,但是当我手动复制方法时,我遇到了运行时错误。此外,我在尝试实例化类B
和C
时遇到了问题,一位同事建议我永远不要在我的设计中使用钻石继承。
因此,我想找到某种"干净"的解决方法,但我无法做到。
我可以将所有初始化例程放在类
A
中,但目前它们被很好地分开了,我想避免有一个大类,在那里我无法真正分离类的不同函数组B
和C
。回答后编辑:这就是我选择的,使用不同的 cpp 文件将我的"大"类拆分为逻辑方法组。我还可以删除继承链接并将它们替换为友谊,其中
B
和C
方法是静态的,并且在类型为A*
的指针上工作。这样,我就可以打电话给B::init(A* a)
,并从D::init(A* a)
C::init(A* a)
。但是,我必须用a->_fooAttribute
替换_fooAttribute
的所有用法,这有点麻烦,似乎不对。
你会推荐什么?
如果您的设计需要钻石继承,那么这就是您需要做的。人们将其视为C++的"不得使用"功能,但事情的真相是它就在那里,它是完全定义的(如果理解起来有点复杂),如果你的问题空间需要它,你应该使用它。
特别是,我无法理解这是否确实是钻石遗产。特别是,B
内部的A
和C
内部的A
是A
的同一实例是否有意义?从你的问题来看,似乎不是。B
和C
都有某种不同的初始化A
方式。如果是这样的话,这不是钻石遗产。只需确保B
和C
在非虚拟继承中继承A
即可。
话虽如此,请确保这确实是您的设计所要求的。你能诚实地说B
是一个A
吗?那C
?你能诚实地说D
既是B
又是C
吗?如果没有,也许让A
成为B
、C
或两者的成员,或者让B
或C
D
的成员更有意义。
如果您从A
继承的唯一原因是作为扩展A
提供的方法的一种方式,那么请考虑简单地将这些方法作为A
的成员。如上所述,虽然减少代码重复是一个有价值的原因,但设计应确保继承关系是一种关系。偏离这一点就是自找麻烦。
继承是一种"是"关系。如果B是A,那么你很好。这同样适用于 C。从你的描述来看,你没有这种关系。相反,您有一个执行计算的实用程序类 (A)。您可能希望使它具有静态方法,因为如果它确实是一个实用程序,则它本身不需要存储任何数据。向 A 传递 B 或 C 的实例并让它使用 B->fooAttribute 访问所需的属性并没有错。但是,您可能希望 B 和 C 都实现一个通用接口,这样您就不必知道您正在查看哪个接口。
- 钻石继承虚拟成员铸造与指针
- 接口的钻石继承(C++)
- c++ 中的函数重载如何在没有钻石继承的情况下工作?
- C++解决没有虚拟继承的钻石继承问题
- 如何调用所有基本类的复制构造函数,以在C 中复制钻石继承中最派生的类对象
- 假设钻石继承打破了C++的封装是否正确?
- C++多个钻石继承和纯虚函数
- 首选钻石继承中一个类的变量
- 钻石继承,C++ 处理
- 将 Boost.Serialization 直接与虚拟钻石继承一起工作
- 钻石继承最低基类构造函数
- 钻石继承方案在 G++ 中编译良好,但在 VC++/Eclipse 中产生警告/错误
- C++ "triangle"(而非钻石)继承
- 让钻石继承发挥作用,但Eclipse仍然抱怨
- 钻石继承与提升::绑定
- 为什么不使用只有一个虚拟继承的钻石继承呢
- 使用 Windows V2 凭据提供程序的钻石继承
- c++虚拟/非虚拟钻石继承
- 带有混合继承修饰符(protected/private/public)的钻石继承
- 避免钻石继承