Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/163.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 多重继承中的构造函数调用序列_C++_Oop_Constructor_Multiple Inheritance - Fatal编程技术网

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