5

所以我有这个想法,我认为用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对象?

我希望这个问题足够清楚。

4

2 回答 2

2

本质上,你是对的。如果您希望这种继承树起作用,您需要LibDerived虚拟派生。LibBase

如果你没有这个,你不能阻止在 下有一个非虚拟,在LibBase下有LibDerived一个单独的虚拟。LibBaseMyBase

于 2009-08-07T15:41:12.167 回答
2

为了简化答案,让我们将虚拟/非虚拟视为重复或非重复的内容。

class LibDerived : LibBase

声明:我允许 LibBase 两次(或更多)进入 LibDerived 的降序

class MyBase : virtual LibBase {};

声明:我允许编译器将 MyBase 降序中的两个 LibBase 条目优化为单个条目。

当这两个声明相互满足时,第一个具有更高的优先级,因此 MyDerived 获得了 LibBase 的 2 个实现。但是 c++ 的力量是解决它的可能性!只需覆盖 MyDerived 虚函数以选择要使用的虚函数。或者另一种方式 - 创建从接口 LibBase 派生的 MyDerived 的通用包装器,该接口聚合任何实例:LibDerived、MyBase、...并从聚合中调用预期的方法。

于 2009-08-07T15:52:12.347 回答