C++ 中的不对称虚拟继承钻石
所以我有这个想法,我认为在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 对象?
我希望这个问题足够清楚。
So I have this idea and I think it's basically impossible to implement in C++... but I want to ask. I read through chapter 15 of Stroustrup and didn't get my answer, and I don't think the billion other questions about inheritance diamonds answer this one, so I'm asking here.
The question is, what happens when you inherit from two base classes which share a common base class themselves, but only one of the two inherits from it virtually. For example:
class CommonBase { ... };
class BaseA : CommonBase { ... };
class BaseB : virtual CommonBase { ... };
class Derived : BaseA, BaseB { ... };
The reason I think I want to do this is because I'm trying to extend an existing library without having to recompile the whole library (don't want to open that can of worms). There already exists a chain of inheritance that I would like to modify. Basically something like this (excuse the ascii art)
LibBase
| \
| \
| MyBase
| |
| |
LibDerived |
| \ |
| \ |
| MyDerived
| |
LibDerived2 |
| \ |
| \ |
| MyDerived2
| |
LibDerived3 |
| \ |
| \ |
| MyDerived3
| |
LibConcrete |
\ |
MyConcrete
Get the picture? I want an object of each of "My
" classes to be an object of the class they are essentially replacing, but I want the next class in the inheritence diagram to use the overridden method implementation from "My
" base class, but all the other methods from the library's classes. The library classes do not inherit virtually so it's like this
class LibDerived : LibBase
But if I make my class inherit virtually
class MyBase : virtual LibBase {};
class MyDerived: virtual MyBase, virtual LibDerived {};
Since MyDerived
will have a vtable, and MyBase
will have a vtable, will there be only one LibBase
object?
I hope this question is clear enough.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
本质上,你是对的。 如果您希望这种继承树发挥作用,您需要从
LibBase
虚拟派生出LibDerived
。如果您没有这个,则无法阻止在
LibDerived
下拥有一个非虚拟LibBase
以及在LibBase
下拥有一个单独的虚拟LibBase
>MyBase。Essentially, you are right. You need to have
LibDerived
derived virtually fromLibBase
if you want this sort of inheritance tree to work.If you don't have this you can't prevent having a non-virtual
LibBase
under theLibDerived
and a separate virtualLibBase
underMyBase
.为了简化答案,让我们将虚拟/非虚拟视为重复或非重复的内容。
声明:我允许 LibBase 两次(或更多)进入 LibDerived 的降序
声明:我允许编译器将 MyBase 降序中的 LibBase 的两个条目优化为单个条目。
当这两个声明满足时,第一个声明具有更高的优先级,因此 MyDerived 获得 LibBase 的 2 个实现。 但是c++的强大功能可以解决这个问题! 只需重写 MyDerived 虚拟函数即可选择您要使用的函数。 或者另一种方式 - 创建从接口 LibBase 派生的 MyDerived 的通用包装器,该包装器聚合任何实例:LibDerived、MyBase...并从聚合中调用预期方法。
To simplify answer let's think about virtual/non-virtual as duplicated or non-duplicated content.
declares: I allow LibBase be twice (or more ) entered into descending of LibDerived
declares: I allow compiler to optimize two entries of LibBase in MyBase descendings into single one.
When these two declarations meet each one, the first is more priority so MyDerived gets 2 implmentation of LibBase. But power of c++ is possibility to resolve it! Just make overriding on MyDerived virtual functions to select which you want to use. Ore another way - create universal wrapper of MyDerived derived from interface LibBase that aggregate any instance: LibDerived, MyBase, ... and call expected method from aggregate.