C++ 多重继承中的构造函数调用序列
我试图找到很多如果在多重继承中只有一个类是虚拟的怎么办? 在这种情况下,我不清楚构造函数调用的行为。 比如说代码-C++ 多重继承中的构造函数调用序列,c++,oop,constructor,multiple-inheritance,C++,Oop,Constructor,Multiple Inheritance,我试图找到很多如果在多重继承中只有一个类是虚拟的怎么办? 在这种情况下,我不清楚构造函数调用的行为。 比如说代码- #include<iostream> using namespace std; class grand{ public: grand(){cout<<"grandfather"<<endl;} }; class parent1:virtual public grand{ //virtual used only here public:
#include<iostream>
using namespace std;
class grand{
public:
grand(){cout<<"grandfather"<<endl;}
};
class parent1:virtual public grand{ //virtual used only here
public:
parent1(){cout<<"parent1 "<<endl;}
};
class parent2: public grand{
public:
parent2(){cout<<"parent2"<<endl;}
};
class child:public parent1,public parent2{
public:
child(){cout<<"child"<<endl;}
};
int main() {
child s;
return 0;
}
但是在上面的代码中,如果我们改变这个
class parent1:virtual public grand{
public:
parent1(){cout<<"parent1 "<<endl;}
};
class parent2: public grand{
public:
parent2(){cout<<"parent2"<<endl;}
};
我关心的是为什么parent1构造函数不以祖父的名字命名 标准规定[C++11第12.6.2/10节]如下: 在非委托构造函数中,初始化在 顺序如下: -首先,并且仅限于最派生类的构造函数, 虚拟基类是按照它们在数据库中出现的顺序初始化的 有向无环图的深度优先左向右遍历 基类,其中“从左到右”是 派生类基类说明符列表中的基类 -然后,按照声明顺序初始化直接基类,如下所示 它们会出现在基本说明符列表中(无论 mem初始值设定项) -然后,非静态数据成员将按照它们被初始化的顺序进行初始化 在类定义中声明(同样不考虑 mem初始值设定项) -最后,执行构造函数主体的复合语句
所以你的虚拟基类总是先建立。。。这在虚拟基类共享的情况下非常重要。标准中说[C++11第12.6.2/10节]: 在非委托构造函数中,初始化在 顺序如下: -首先,并且仅限于最派生类的构造函数, 虚拟基类是按照它们在数据库中出现的顺序初始化的 有向无环图的深度优先左向右遍历 基类,其中“从左到右”是 派生类基类说明符列表中的基类 -然后,按照声明顺序初始化直接基类,如下所示 它们会出现在基本说明符列表中(无论 mem初始值设定项) -然后,非静态数据成员将按照它们被初始化的顺序进行初始化 在类定义中声明(同样不考虑 mem初始值设定项) -最后,执行构造函数主体的复合语句
所以你的虚拟基类总是先建立。。。这在虚拟基类共享的情况下非常重要。可能重复的否这是关于调用顺序而不是共享本身。可能重复的否这是关于调用顺序而不是共享本身。谢谢。正如您所说的,虚拟类是先构建的,但读过这篇文章后仍然不清楚为什么“parent1”不是在“祖父”之后才调用。请在回答中添加一些示例好吗?好的,您必须首先为
parent2
构建虚拟基类(规则1)。然后您必须按照声明的顺序构建parent1
,然后构建parent2
(规则2)。但是要构建parent1
您需要首先构建一个grand
实例,而不是虚拟实例(规则2)。因此,这将为您提供以下顺序:grand
(虚拟),grand
(对于parent1),parent1
,parent2
(使用最初构建的虚拟grand),然后是子项
。尽管我猜可能是什么,有人能清楚地指定什么是:mem初始值设定项和基本说明符列表吗?谢谢。谢谢。正如你所说的,虚拟类是先构建的,但读完这篇文章后,仍然不清楚为什么“parent1”不在“祖父”后面调用。你能在回答中添加一些例子吗?好的,你必须先为parent2
构建虚拟基类(规则1)。然后您必须按照声明的顺序构建parent1
,然后构建parent2
(规则2)。但是要构建parent1
您需要首先构建一个grand
实例,而不是虚拟实例(规则2)。因此,这将为您提供以下顺序:grand
(虚拟),grand
(对于parent1),parent1
,parent2
(使用最初构建的虚拟grand),然后是子项
。尽管我猜可能是什么,有人能清楚地指定什么是:mem初始值设定项和基本说明符列表吗?非常感谢。
class parent1:virtual public grand{
public:
parent1(){cout<<"parent1 "<<endl;}
};
class parent2: public grand{
public:
parent2(){cout<<"parent2"<<endl;}
};
class parent1:public grand{ //virtual removed from here
public:
parent1(){cout<<"parent1 "<<endl;}
};
class parent2:virtual public grand{ //virtual is added here
public:
parent2(){cout<<"parent2"<<endl;}
};
grandfather
grandfather //why parent1 constructor is not called here?
parent1
parent2
child