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类的默认构造函数?
答案 0 :(得分:1)
由于B
中C
的{{1}}部分没有显式初始化,编译器使用C::C()
的默认构造函数来执行此操作。
B
相当于:
C()
: A(1) {
cout << "C class" << endl;
}
C()
: B(), A(1) {
cout << "C class" << endl;
}
的默认构造函数尝试使用B
的默认构造函数初始化A
部分,该构造函数不存在。这是编译器错误消息。
您可以通过以下方法之一修复它:
A
提供默认构造函数。A
提供默认构造函数,其中使用B
初始化A(int)
的{{1}}部分。<强>更新强>
为什么编译器想在A
中想要B
?因为它不知道在运行时会构造A::A()
的实例。
采取以下方案:
B::B()
很清楚为什么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
。
答案 1 :(得分:0)
B
没有默认构造函数。
B
没有用户定义的默认构造函数,并且编译器提供的默认构造函数将是格式错误的,因为它必须使用A
默认构造函数,而A
具有无。
即使B
默认构造函数在A
用作基类时不应调用B
构造函数,如果需要,仍需要B
的有效默认构造函数使用它。
答案 2 :(得分:0)
以下是C ++ 11中问题的细分:
由于B
没有用户声明的构造函数,因此没有参数的构造函数被隐式声明为默认值。但是,由于A
没有默认构造函数,因此该构造函数被定义为已删除。参考[class.ctor]#5
。 (这实际上意味着永远不能创建B
,因为它没有未删除的构造函数。)
C
的构造函数未在其初始化列表中提及B
,因此B
子对象已默认初始化。参考[class.base.init]#8
没有可访问的默认构造函数的对象的默认初始化意味着程序格式错误。参考[dcl.init]#6
[class.base.init]#8
中有一个子句,如果基类是抽象类的虚基类,则它不需要构造函数。然而,这不是这种情况。 A
就是这样一个类,但B
不是。
摘要 - B
的{{1}}子对象没有有效的构造函数。