【问题标题】:c++ virtual inheritanceC++ 虚拟继承
【发布时间】:2011-01-08 18:01:10
【问题描述】:

问题:

class Base {
public:
  Base(Base* pParent);
  /* implements basic stuff */
};

class A : virtual public Base {
public:
  A(A* pParent) : Base(pParent) {}
  /* ... */
};

class B : virtual public Base {
public:
  B(B* pParent) : Base(pParent) {}
  /* ... */
};

class C : public A, public B {
public:
  C(C* pParent) : A(pParent), B(pParent) {} // - Compilation error here
  /* ... */
};

在给定的位置,gcc 抱怨它无法匹配对 Base() 的函数调用,即默认构造函数。但是C并没有直接从Base继承,只能通过A和B。那么为什么gcc会在这里抱怨呢?

想法? TIA /罗伯

【问题讨论】:

  • 编译是用no-rtti设置完成的,可能有问题吗?
  • 不,继承是编译时的事情,不需要RTTI。

标签: c++ gcc virtual virtual-inheritance


【解决方案1】:

virtual 基类的特殊之处在于它们由最派生类初始化,而不是由继承自虚拟基的任何中间基类初始化。哪个潜在的多个初始化器将是初始化一个基的正确选择?

如果正在构造的最派生类未将其列在其成员初始化列表中,则虚拟基类将使用其默认构造函数进行初始化,该构造函数必须存在且可访问。

请注意,允许在构造函数的初始化程序列表中使用虚拟基标识符,即使它不是相关类的直接基。

【讨论】:

  • 附录:请注意,抽象类永远无法初始化其虚拟基,因此即使不存在 default-ctor,也无需在其 ctors init-list 中调用虚拟基 ctor。
  • 那么这意味着A和B的父类初始化(即':Base(pParent)')在构造更多派生类时都被忽略了?
【解决方案2】:

您需要从 C 显式调用 Base 的构造函数:

class C : public A, public B {
public:
C(C* pParent) : Base(pParent), A(pParent), B(pParent) {}
/*... */
};

【讨论】:

  • 我不知道你能做到这一点。这是否意味着编译器忽略了 AB 的 c'tors 中的代码,它们似乎初始化了 Base
  • 不仅可以你这样做,你必须这样做。没有代码被忽略。 Base 的构造函数只会被调用一次,然后是 A 和 B 的构造函数体,然后是 C 的构造函数体。
  • 我现在了解了构造函数调用的顺序和背后的原因,除了我通常有一个只有默认构造函数的基类,所以我不必显式调用Base() .当然,在 OP 的示例中,编译器仍然必须忽略程序员的指示,即应直接从 AB 的 c'tors 调用 Base(pParent)
  • 实际上,我认为编译器看到virtual 继承涉及到这种情况,就偷偷地为自己提供了几个不同的构造函数,并且知道每种情况下最派生的 c'tor 被调用, 总是调用正确的构造函数序列。
  • 正确。虚拟继承引入了一层间接性,因此共享基类只被构造和分配一次。
【解决方案3】:

如果您声明自定义构造函数,则默认构造函数将被禁用。虚继承需要直接调用虚继承的构造函数,否则不知道是A初始化还是B初始化。

【讨论】:

    猜你喜欢
    • 2016-03-26
    • 1970-01-01
    • 2017-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多