虚拟继承(菱形) - 为什么我需要从最底层的派生类向上转换为基类
请考虑以下事项:
#include <iostream>
#include <string>
using namespace std;
class A {
public:
A(const char* sName) //conversion constructor
: _sName(sName) {cout<<"(1)"<<endl;} ;
A(const A& s) {cout<<"(2)"<<endl;} //copy constructor
virtual ~A() {cout<<"(3)"<<endl;} //destructor
void f1() {cout<<"(4)"<<endl; f2();} //Notice two commands!
virtual void f2() =0;
private:
string _sName;
};
class B1: virtual public A {
public:
B1(const char* sAName, const char* sSName)
: _sName1(sAName), A(sSName) {cout<<"(5)"<<endl;}
B1(const B1& b1) : A(b1) {cout<<"(6)"<<endl;}
~B1() {cout<<"(7)"<<endl;}
virtual void f1() {cout<<"(8)"<<endl;}
virtual void f2() {cout<<"(9)"<<endl; f3();}
virtual void f3() {cout<<"(10)"<<endl;}
private:
string _sName1;
};
class B2: virtual public A {
public:
B2(const char* sAName, const char* sSName)
: _sName2(sAName), A(sSName) {cout<<"(11)"<<endl;}
B2(const B2& b2) : A(b2) {cout<<"(12)"<<endl;}
~B2() {cout<<"(13)"<<endl;}
virtual void f3() {f1(); cout<<"(14)"<<endl;}
private:
string _sName2;
};
class C: public B1, public B2 {
public:
C () : A(" this is A ") , B1(" this is " , " B1 ") , B2 (" this is " , " B2 ") {}
C (const C& c) : A(c) , B1(c) , B2(c) {}
~C() {cout<<"(15)"<<endl;}
virtual void f1() {A::f1(); cout<<"(16)"<<endl;}
void f3 () {cout<<"(17)"<<endl;}
};
int main() {
/* some code */
return 0;
}
正如您所看到的,我在class C
中添加了 C 的 Ctor(构造函数)的实现。我不清楚的是,如果 B1 在其 Ctor 中为我完成这项工作,为什么我还需要从 C 到 A 的上转型? 意思是,如果我将 C's Ctor 写为:
C () : A(" this is A ") , B1(" this is " , " B1 ") , B2 (" this is " , " B2 ") {}
为什么我不能写:
C () : B1(" this is " , " B1 ") , B2 (" this is " , " B2 ") {}
谢谢, 罗南
consider the following :
#include <iostream>
#include <string>
using namespace std;
class A {
public:
A(const char* sName) //conversion constructor
: _sName(sName) {cout<<"(1)"<<endl;} ;
A(const A& s) {cout<<"(2)"<<endl;} //copy constructor
virtual ~A() {cout<<"(3)"<<endl;} //destructor
void f1() {cout<<"(4)"<<endl; f2();} //Notice two commands!
virtual void f2() =0;
private:
string _sName;
};
class B1: virtual public A {
public:
B1(const char* sAName, const char* sSName)
: _sName1(sAName), A(sSName) {cout<<"(5)"<<endl;}
B1(const B1& b1) : A(b1) {cout<<"(6)"<<endl;}
~B1() {cout<<"(7)"<<endl;}
virtual void f1() {cout<<"(8)"<<endl;}
virtual void f2() {cout<<"(9)"<<endl; f3();}
virtual void f3() {cout<<"(10)"<<endl;}
private:
string _sName1;
};
class B2: virtual public A {
public:
B2(const char* sAName, const char* sSName)
: _sName2(sAName), A(sSName) {cout<<"(11)"<<endl;}
B2(const B2& b2) : A(b2) {cout<<"(12)"<<endl;}
~B2() {cout<<"(13)"<<endl;}
virtual void f3() {f1(); cout<<"(14)"<<endl;}
private:
string _sName2;
};
class C: public B1, public B2 {
public:
C () : A(" this is A ") , B1(" this is " , " B1 ") , B2 (" this is " , " B2 ") {}
C (const C& c) : A(c) , B1(c) , B2(c) {}
~C() {cout<<"(15)"<<endl;}
virtual void f1() {A::f1(); cout<<"(16)"<<endl;}
void f3 () {cout<<"(17)"<<endl;}
};
int main() {
/* some code */
return 0;
}
As you can see , I added in class C
the implementation of C's Ctor (constructor) . What is not clear to me is why do I need also the upcast from C to A , if B1 does that job for me in its Ctor ?
Meaning , if I wrote C's Ctor as :
C () : A(" this is A ") , B1(" this is " , " B1 ") , B2 (" this is " , " B2 ") {}
why can't I write :
C () : B1(" this is " , " B1 ") , B2 (" this is " , " B2 ") {}
thanks ,
Ronen
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
虚拟基的构造函数在非虚拟 Anestors 构造函数之前调用。在您的示例中,B1 ctor 无法调用 C 的虚拟基构造函数,因为稍后将调用 B1 ctor 本身。
Constructor of virtual base is called before nonvirtual ansestors ctor's. In your example B1 ctor can not invoke the virtual base constructor for C as B1 ctor itself will be called later.
简而言之,因为这是标准所要求的:您必须在最派生类的构造函数中初始化虚拟基。
更详细的答案是,这是因为您只有一个用于虚拟基的基子对象,并且该子对象可能在不同的基类中以不同的方式初始化。例如,在您的示例中,
您希望将什么值传递给 A ctor,“ B1 ”或“ B2 ”?
In short, because it's what standard requires: you have to initialize virtual base in the ctor of the most derieved class.
A more elaborated answer, it's because you have only one base sub-object for virtual bases and this sub-object might be initialized differently in different base classes. E.g. in your example
What value do you expect to be passed to A ctor, " B1 " or " B2 "?
因为“B1”和“B2”都使用与“C”相同的内存。如果您没有指定“C”中“A”的构造,则“B1”或“B2”中的哪一个应该构造“A”?
你的术语在这里有点错误——这不是对“A”的升级。
Because 'B1' and 'B2' both use the same memory for 'A' that 'C' does. If you didn't specify the construction of 'A' in 'C', which one of 'B1' or 'B2' should construct 'A'?
Your terminology is slightly wrong here - this is not an upcast to 'A'.
因为你的
类A
没有默认构造函数。编译器为每个类生成一个默认构造函数,但是一旦您显式重载该构造函数,它就会假设您想要做一些特殊的事情,并且它不会生成默认构造函数,并且当您的代码尝试调用默认构造函数时,它会导致错误。
以下代码语句:
导致调用类 A 的默认构造函数,而该构造函数根本不存在,因此会导致错误。如果您为
A 类
提供默认构造函数,则应该编译正常 也没有任何错误。Because your
class A
does not have default constructor.Compiler generates an default constructor for every class but once you explicitly overload the constructor it assumes you want to do something special and it does not generate the default constructor and when your code tries to invoke the default constructor it leads to an error.
The following code statement:
leads to calling of the class A default constructor, which is not there at all, and hence results in an error. If you provide an default constructor for your
class A
that should compile fine without any errors too.这是一个快速尝试:
此示例输出:
也就是说,似乎在最派生的类中需要调用
A::A()
,因为继承是virtual
code>,实例化C
时,它不会被B1
或B2
的构造函数调用。Here is a quick try:
This example outputs:
That is, it seems that the call to
A::A()
is required in the most derived class because since the inheritance isvirtual
, it won't get called by the constructors ofB1
orB2
when instantiatingC
.