【问题标题】:multi level inheritance constructor execution多级继承构造函数执行
【发布时间】:2014-06-22 04:57:58
【问题描述】:
class A {
public:
    A(int) {
        cout << "Base class" << endl;
    }
};

class B : virtual public A {
public:
    virtual void do_something() = 0;
};

class C : public B {
public:
    C()
        : A(1) {
        cout << "C class" << endl;
    }

    virtual void do_something() {
    }
};

编译器错误:当为 C 创建对象时,编译器会产生类似

的错误

错误:没有匹配的函数调用'A::A()'

为什么编译器需要 A 类的默认构造函数?

【问题讨论】:

标签: c++


【解决方案1】:

由于C::C()CB 部分没有显式初始化,因此编译器使用B 的默认构造函数来执行此操作。

C()
    : A(1) {
    cout << "C class" << endl;
}

相当于:

C()
    : B(), A(1) {
    cout << "C class" << endl;
}

B 的默认构造函数尝试使用不存在的A 的默认构造函数来初始化A 部分。那是编译器错误信息。

您可以通过以下方法之一修复它:

  1. A 提供默认构造函数。
  2. B 提供一个默认构造函数,其中使用A(int) 来初始化BA 部分。

更新

为什么编译器要在B::B() 中加入A::A()?因为它不知道在运行时会构造一个C 的实例。

假设以下场景:

#include <iostream>
using namespace std;

class A
{
   public:
      A(int)
      {
         cout << "Came to A(int)" << endl;
      }
};

class B : virtual public A
{
   public:
      virtual void do_something(){};
};

int main()
{
   B b;
}

很清楚为什么B::B() 需要调用A::A(int) 或期待A::A()。由于编译器无法先验地确定B 是否是派生最多的类,因此它必须确保有一种方法可以在必要时从B 初始化A

【讨论】:

  • 最派生类负责A子对象的初始化,因为它是虚拟继承的。
  • 找到引用(§10.1 [class.mi]/4):对于每个指定为虚拟的不同基类,最派生的对象应包含该类型的单个基类子对象
  • @chris,我同意你所说的。这仍然留下了一个问题:B 是如何初始化的?这就是 OP 的代码出现编译器错误的地方。
  • 好吧,当然,B 的默认构造函数被调用了,但我认为不应该调用A 的。
  • 哦,here we go。这就是我一直在寻找的东西,但由于某种原因找不到。 B() 绝对不应该打电话给A()
【解决方案2】:

B 没有默认构造函数。

B 没有用户定义的默认构造函数,编译器提供的默认构造函数格式不正确,因为它必须使用A 默认构造函数,而A 没有。

即使B 用作基类时B 默认构造函数不应调用A 构造函数,但如果您想使用B,您仍然需要一个有效的默认构造函数。

【讨论】:

    【解决方案3】:

    以下是问题的细分,在 C++11 中:

    • 由于B 没有用户声明的构造函数,因此没有参数的构造函数被隐式声明为默认值。但是,由于A 没有默认构造函数,因此该构造函数定义为已删除。参考[class.ctor]#5。 (这实际上意味着永远无法创建 B,因为它没有未删除的构造函数。

    • C 的构造函数在其初始化列表中没有提及B,因此B 子对象是默认初始化的。参考[class.base.init]#8

    • 没有可访问的默认构造函数的对象的默认初始化意味着程序格式错误。参考[dcl.init]#6

    [class.base.init]#8 中有一个子句,基类不需要构造函数如果它是抽象类的虚拟基类。然而,这里的情况并非如此。 A 是这样一个类,但 B 不是。

    总结 - CB 子对象没有有效的构造函数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-31
      • 2014-09-02
      • 1970-01-01
      • 2011-07-06
      • 2013-06-01
      • 2023-04-03
      相关资源
      最近更新 更多