问题描述
很抱歉,这感觉像是my last question.的廉价续集
我有一个钻石继承人,其中D
既来自B
和C
,又来自A
(实际上)。 A
,B
和C
是抽象的,由于我以前的问题的回答,编译器现在已经意识到了,一切都很好。
现在,我需要创建一个从E
派生的类D
。据我所知,通常构造函数E::E
应该调用D::D
,并且调用D::D
,A::A
,和B::B
。
但是我的编译器确实坚持要C::C
本身调用E::E
。
这是我做的一个简单示例:
A::A
这是编译错误:
class A { //abstract
protected:
A(int foo) {}
virtual void f() =0;
};
class B: public virtual A { // abstract
protected:
B() {}
};
class C: public virtual A { // abstract
protected:
C() {}
};
class D: public B,public C { // concrete
public:
D(int foo,int bar) :A(foo) {}
void f() {}
};
class E: public D { // concrete
public:
E(int foo,int bar,int buz) :D(foo,bar) {}
};
int main()
{
return 0;
}
我知道虚拟继承是正确的,并且我知道编译器知道我打算抽象哪些类以及可以实例化哪些类,因为如果删除$ g++ test.cpp
test.cpp: In constructor ‘E::E(int,int,int)’:
test.cpp:25:49: error: no matching function for call to ‘A::A()’
25 | E(int foo,bar) {}
| ^
test.cpp:3:9: note: candidate: ‘A::A(int)’
3 | A(int foo) {}
| ^
test.cpp:3:9: note: candidate expects 1 argument,0 provided
test.cpp:1:7: note: candidate: ‘constexpr A::A(const A&)’
1 | class A { //abstract
| ^
test.cpp:1:7: note: candidate expects 1 argument,0 provided
test.cpp:1:7: note: candidate: ‘constexpr A::A(A&&)’
test.cpp:1:7: note: candidate expects 1 argument,0 provided
,代码就会编译。
我想念什么?
解决方法
但是我的编译器确实坚持要求E :: E本身调用A :: A。
就像我在回答上一个问题时所解释的那样:“派生最多的类的构造函数调用虚拟基础的构造函数” 。
包含虚拟基的层次结构中的所有非抽象类必须正确初始化虚拟基,因为它们可能会被实例化为派生程度最高的类。例如,如果您创建E
的实例,那么E
的构造函数将初始化虚拟基础A
。
在您的代码中,E
的构造函数尝试通过省略初始化程序来使用默认的A
构造函数。但是A
无法默认构造,因此程序格式错误。
我想念什么?
A
的构造函数中虚拟基础E
的初始化程序。
据我所知,无法将虚拟基础的构建委派给其他具体基础,例如D
。