C++ 构造函数调用具有组合的顺序

C++ 构造函数调用具有组合的顺序,c++,inheritance,constructor,composition,C++,Inheritance,Constructor,Composition,我有a班和B班。类C派生自类B,并以类A对象作为组合 这意味着首先调用REF_BASE2,然后调用REF_BASE1,然后调用REF构造函数。 如果我们把它定义为 REF (int ii) : REF_BASE1(ii), REF_BASE2 (ii) { 这意味着首先调用REF_BASE1,然后调用REF_BASE2,然后调用REF构造函数 然而,在我上面的程序中,我明确地“错误地”指出,通过内部组合变量A,A应该先初始化,然后B应该得到初始化,然而编译器的方法是正确的,但没有让我知道我的错

我有a班和B班。类C派生自类B,并以类A对象作为组合

这意味着首先调用REF_BASE2,然后调用REF_BASE1,然后调用REF构造函数。 如果我们把它定义为

REF (int ii) : REF_BASE1(ii), REF_BASE2 (ii) {
这意味着首先调用REF_BASE1,然后调用REF_BASE2,然后调用REF构造函数

然而,在我上面的程序中,我明确地“错误地”指出,通过内部组合变量A,A应该先初始化,然后B应该得到初始化,然而编译器的方法是正确的,但没有让我知道我的错误

无论我在派生类constcutor初始化列表中指定的顺序如何,上述程序的输出都是

Constructor of B is called 

 Constructor of A is called 

 Constructor of C is called 

 destructor  of C is called 

 destructor  of A is called 

 destructor  of B is called 
我的问题是 1) 为什么编译器不抱怨?或者我是对的?
2) 派生构造函数中的顺序是否没有严格遵循

我将从第二个问题开始:

2) 派生构造函数中的顺序是否没有严格遵循

顺序不是出现在构造函数的初始化列表中的顺序,而是基类出现在类定义中的顺序

因此,如果您的类定义如下所示:

struct A : B, C
{
    // ...
};
然后,无论您在
A
的构造函数的初始化列表中指定了什么顺序,都会在
C
的构造函数之前调用
B
的构造函数

C++11标准第12.6.2/10段规定:

在非委托构造函数中,初始化按以下顺序进行:

-首先,并且仅对于派生最多的类(1.8)的构造函数,虚拟基类在 它们在基类的有向无环图的深度优先的从左到右遍历中出现的顺序, 其中“从左到右”是派生类基类说明符列表中基类的出现顺序

-然后,直接基类按照它们在基说明符列表中出现的声明顺序初始化 (不考虑mem初始值设定项的顺序)

-然后,按照类定义中声明的顺序初始化非静态数据成员 (同样,无论mem初始值设定者的顺序如何)

-最后,执行构造函数主体的复合语句

第一个问题:

1) 为什么编译器不抱怨


编译器可能会警告您,构造函数初始值设定项列表中的初始化顺序不同于基类列表中的初始化顺序(GCC使用
-Wall
),但不必如此。最后,只有后者才重要。

我将从第二个问题开始:

2) 派生构造函数中的顺序是否没有严格遵循

顺序不是出现在构造函数的初始化列表中的顺序,而是基类出现在类定义中的顺序

因此,如果您的类定义如下所示:

struct A : B, C
{
    // ...
};
然后,无论您在
A
的构造函数的初始化列表中指定了什么顺序,都会在
C
的构造函数之前调用
B
的构造函数

C++11标准第12.6.2/10段规定:

在非委托构造函数中,初始化按以下顺序进行:

-首先,并且仅对于派生最多的类(1.8)的构造函数,虚拟基类在 它们在基类的有向无环图的深度优先的从左到右遍历中出现的顺序, 其中“从左到右”是派生类基类说明符列表中基类的出现顺序

-然后,直接基类按照它们在基说明符列表中出现的声明顺序初始化 (不考虑mem初始值设定项的顺序)

-然后,按照类定义中声明的顺序初始化非静态数据成员 (同样,无论mem初始值设定者的顺序如何)

-最后,执行构造函数主体的复合语句

第一个问题:

1) 为什么编译器不抱怨


编译器可能会警告您,构造函数初始值设定项列表中的初始化顺序不同于基类列表中的初始化顺序(GCC使用
-Wall
),但不必如此。最后,只有后一个问题才重要。

编译器为我发出警告:“字段“a”将在基“B”[-Wreorder]之后初始化”。编译器为我发出警告:“字段“a”将在基“B”[-Wreorder]之后初始化。”
struct A : B, C
{
    // ...
};