所以我有这个想法,我认为用C ++实现基本上是不可能的......但是我想问一下。我读完Stroustrup的第15章并没有得到我的答案,我不认为关于继承钻石的其他十亿个问题都回答了这个问题,所以我在这里问。
问题是,当你从两个共享一个公共基类的基类继承时会发生什么,但是这两个基类中只有一个虚拟地从它继承。例如:
class CommonBase { ... };
class BaseA : CommonBase { ... };
class BaseB : virtual CommonBase { ... };
class Derived : BaseA, BaseB { ... };
我认为我想这样做的原因是因为我试图扩展现有的库而不必重新编译整个库(不想打开那些蠕虫)。已经存在我想要修改的继承链。基本上是这样的(原谅ascii艺术)
LibBase
| \
| \
| MyBase
| |
| |
LibDerived |
| \ |
| \ |
| MyDerived
| |
LibDerived2 |
| \ |
| \ |
| MyDerived2
| |
LibDerived3 |
| \ |
| \ |
| MyDerived3
| |
LibConcrete |
\ |
MyConcrete
拍照?我希望每个“My
”类的对象是它们实际上替换的类的对象,但我希望继承图中的下一个类使用重写的方法实现来自“My
”基类,但来自库类的所有其他方法。库类几乎没有继承,所以它就像这样
class LibDerived : LibBase
但如果我让我的班级继承虚拟
class MyBase : virtual LibBase {};
class MyDerived: virtual MyBase, virtual LibDerived {};
由于MyDerived
将有一个vtable,MyBase
将有一个vtable,是否只有一个LibBase
对象?
我希望这个问题很清楚。
答案 0 :(得分:2)
基本上,你是对的。如果您希望这种继承树工作,则需要从LibDerived
虚拟派生LibBase
。
如果您没有此功能,则无法阻止LibBase
下的非虚拟LibDerived
和LibBase
下的单独虚拟MyBase
。
答案 1 :(得分:2)
为简化回答,让我们将虚拟/非虚拟视为重复或非重复内容。
class LibDerived : LibBase
声明:我允许LibBase两次(或更多次)进入LibDerived的降序
class MyBase : virtual LibBase {};
声明:我允许编译器将MyBase下降中的两个LibBase条目优化为单个条目。
当这两个声明遇到每个声明时,第一个声明会更优先,因此MyDerived会获得2个LibBase的声明。但c ++的力量是解决它的可能性!只需覆盖MyDerived虚拟功能,即可选择要使用的功能。另一种方式 - 创建从接口LibBase派生的MyDerived的通用包装器,它聚合任何实例:LibDerived,MyBase,...并从聚合调用预期方法。