[英]Virtual inheritance (diamond) - Why do I need to upcast to Base class from the most Derived class
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) . 如您所见,我在
class C
添加了C的Ctor(构造函数)的实现。 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 ? 对我来说不清楚的是,如果B1在其Ctor中替我完成了工作,为什么我也需要从C到A的上行? Meaning , if I wrote C's Ctor as :
意思是,如果我将C的Ctor写成:
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 谢谢罗尼
In short, because it's what standard requires: you have to initialize virtual base in the ctor of the most derieved class. 简而言之,因为这是标准的要求:您必须在最受剥夺的类的ctor中初始化虚拟基数。
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. 一个更详尽的答案是,因为您只有一个用于虚拟基础的基础子对象,并且此子对象可能在不同的基础类中以不同的方式初始化。 Eg in your example
例如在您的示例中
C () : B1(" this is " , " B1 ") , B2 (" this is " , " B2 ") {}
What value do you expect to be passed to A ctor, " B1 " or " B2 "? 您希望将什么值传递给“ b1”或“ b2”?
Constructor of virtual base is called before nonvirtual ansestors ctor's. 虚拟基础的构造函数在非虚拟anstors ctor 之前被称为。 In your example B1 ctor can not invoke the virtual base constructor for C as B1 ctor itself will be called later.
在您的示例中,B1 ctor无法调用C的虚拟基本构造函数,因为B1 ctor本身将在以后被调用。
Because 'B1' and 'B2' both use the same memory for 'A' that 'C' does. 因为“ B1”和“ B2”都使用与“ C”相同的“ A”存储空间。 If you didn't specify the construction of 'A' in 'C', which one of 'B1' or 'B2' should construct 'A'?
如果未在“ C”中指定“ A”的构造,那么“ B1”或“ B2”中的哪一个应构造“ A”?
Your terminology is slightly wrong here - this is not an upcast to 'A'. 您的术语在这里有点错误-这不是对'A'的偏up。
Because your class A
does not have default constructor. 因为您的
class A
没有默认构造函数。
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: 以下代码语句:
C () : B1(" this is " , " B1 ") , B2 (" this is " , " B2 ") {}
leads to calling of the class A default constructor, which is not there at all, and hence results in an error. 导致调用类A的默认构造函数,该构造函数根本不存在,因此导致错误。 If you provide an default constructor for your
class A
that should compile fine without any errors too. 如果您为
class A
提供了默认构造函数,则该构造函数也可以正常编译而不会出现任何错误。
Here is a quick try: 这是一个快速尝试:
#include <iostream>
class A { public: A(int v) : m_v(v) { std::cout << "Initializing A with " << v << std::endl; } int m_v; };
class B1 : public virtual A { public: B1(int v) : A(v) {} };
class B2 : public virtual A { public: B2(int v) : A(v) {} };
class C : public B1, public B2 { public: C(int v1, int v2, int v3) : A(v1), B1(v2), B2(v3) {} };
int main()
{
C c(1, 2, 3);
std::cout << "c.m_v: " << c.m_v << std::endl;
return EXIT_SUCCESS;
}
This example outputs: 此示例输出:
Initializing A with 1
c.m_v: 1
That is, it seems that the call to A::A()
is required in the most derived class because since the inheritance is virtual
, it won't get called by the constructors of B1
or B2
when instantiating C
. 也就是说,似乎在最派生的类中需要对
A::A()
进行调用,因为由于继承是virtual
,因此在实例化C
时B1
或B2
的构造函数不会调用它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.