虚拟继承 - 钻石问题 - 真正发生的事情

时间:2014-04-02 19:04:20

标签: c++ virtual-inheritance

我理解并已经阅读了关于通过虚拟继承解决的钻石问题。我的问题是

  

"将虚拟放置在您将继承的基类旁边实际意味着"

class A { public: void Foo() {} };
class B : virtual public A {};
class C : virtual public A {};
class D : public B, public C {};

我想知道我的理解是否正确。在声明中

  class D : public B, public C {}

编译器将遍历第一个基类B,并注意到它几乎从class A继承。编译器将检查是否存在类A的实例,否则它将创建由B派生的A的实例。然后,编译器将遍历C类,并注意它实际上是从A类继承的。但是,由于它实际上是由C继承而A的实例已经存在,因此它不会包含新实例。从而解决钻石问题。这种理解是否正确?

1 个答案:

答案 0 :(得分:1)

是的,您的理解是正确的,但很难说出虚拟继承真正合理的情况,即使在这些情况下,问题通常可以通过更简单的其他方式来解决。

在您的情况下,您的D实例将是C,B和单个A实例的组合。由于A和B都可以在具有不同组成的不同场景中发挥作用,其中A实际上由许多类继承(可能甚至比A和B更多的类),因此不清楚如何布置例如D实例的构建块。记忆。因此,为类B和C编译的代码通常使用实用程序指针或偏移量(每个实例1个指针,一个用于B,一个用于C),这些指针指向由继承的不同类的代码共享的A实例。实际上来自A类。这会占用D实例中的额外空间,并通过使用这些指针来降低代码的效率。

另一个丑陋的实现细节是,在D类的情况下,当你创建/初始化D的实例时,你的B和C实例都是"赛车"从构造函数中调用类A的构造函数。因此,您的D实例还将包含一个bool变量,该变量指示某人是否已从其构造函数中调用了A的ctor。其中一个B和C的ctors将赢得并将此bool变量设置为true,因此以下尝试来自其他"虚拟后代"检查特定的bool值后,只需拯救。

虚拟继承只是丑陋而且尽可能避免。

相关问题