多级继承构造函数的执行

multi level inheritance constructor execution

本文关键字:执行 构造函数 继承 多级      更新时间:2023-10-16
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::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

B没有默认构造函数。

B没有用户定义的默认构造函数,编译器提供的默认构造函数是错误的,因为它必须使用A的默认构造函数,而A没有。

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

下面是c++ 11中问题的详细说明:

  • 由于B没有用户声明的构造函数,因此没有参数的构造函数被隐式声明为默认值。然而,由于A没有默认构造函数,这个构造函数被定义为删除的。Ref [class.ctor]#5。(这实际上意味着B永远不能被创建,因为它没有未删除的构造函数)。

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

  • 没有可访问的默认构造函数的对象的默认初始化意味着程序是病态的。Ref [dcl.init]#6

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

Summary - CB子对象没有有效的构造函数