简体   繁体   English

C ++:构造和初始化顺序保证

[英]C++: Construction and initialization order guarantees

I have some doubts about construction and initialization order guarantees in C++. 我对C ++中的构造和初始化顺序保证有些怀疑。 For instance, the following code has four classes X , Y , Z and W . 例如,以下代码有四个类XYZW The main function instantiates an object of class X , which contains an object of class Y , and derives from class Z , so both constructors will be called. main函数实例化一个class X对象,它包含一个class Y对象,并从class Z派生,因此将调用两个构造函数。 Additionally, the const char* parameter passed to X 's constructor will be implicitly converted to an object of class W , so W 's constructor must also be called. 另外,传递给X的构造const char*参数将被隐式转换为class W的对象,因此也必须调用W的构造函数。

What are the guarantees the C++ standard gives on the order of the calls to the copy constructors? C ++标准对复制构造函数的调用顺序有什么保证? Or, equivalently, what this program is allowed to print? 或者,等效地,该程序可以打印什么?

#include <iostream>

class Z {
   public:
   Z() { std::cout << "Z" << std::endl; }
};

class Y {
   public:
   Y() { std::cout << "Y" << std::endl; }
};

class W {
   public:
   W(const char*) { std::cout << "W" << std::endl; }
};

class X : public Z {
   public:
   X(const W&) { std::cout << "X" << std::endl; }
   private:
   Y y;
};

int main(int, char*[]) {
   X x("x");
   return 0;
}

edit: Is this correct? 编辑:这是对的吗?

   W      |
 /   \    |
Z     Y   |
 \   /    |
   X      V

In all classes construction order is guaranteed: base classes, as specified from left to right followed by member variables in the order declared in the class definition. 在所有类中,构造顺序都是有保证的:基类,从左到右指定,后跟成员变量,在类定义中声明的顺序。 A class's constructor body is executed once all of its bases' and members' constructions have completed. 类的构造函数体在其所有基础和成员构造完成后执行。

In your example X is derived from Z and contains Y so the Z base object is constructed first, then the Y member y , then the construction of the X completes with the execution of X 's constructor body. 在你的例子中, X是从Z派生并包含Y所以首先构造Z基础对象,然后构造Y成员y ,然后X的构造完成X的构造函数体的执行。

The temporary W is needed to pass to the constructor of X , so it is constructed before the construction of the x begins and will be destroyed once the initialization of x completes. 临时W需要传递给的构造X ,所以施工前将其构造x开始,曾经的初始化将被销毁x完成。

So the program must print: 所以程序必须打印:

W
Z
Y
X

1) First of all, it is needed to calculate the arguments. 1)首先,需要计算参数。

2) Then base classes are constructed. 2)然后构造基类。

3) Then members are constructed in the order of appearance in the declaration of the class. 3)然后按照班级声明中的出现顺序构建成员。

4) Then Constructor of X is called 4)然后调用X的构造函数

  1. The W object will be constructed before the constructor to X is called. W对象将在调用X的构造函数之前构造。
  2. Z, as a base class of X, will be initialized before the members of X. Z,作为X的基类,将在X的成员之前初始化。
  3. Y will be initalized during member initialization 在成员初始化期间,Y将被初始化
  4. X's constructor will run. X的构造函数将运行。

To expand on Charles Bailey's answer, the rules change when your base classes are inherited virtually. 为了扩展Charles Bailey的答案,当您的基类被虚拟继承时,规则会发生变化。 I always forget what the order is, the IBM site says that virtual bases are initialized first but I've just never run into a case where it's actually more than trivia. 我总是忘记订单是什么,IBM网站说虚拟基地首先被初始化,但我从来没有遇到过它实际上不仅仅是琐事的情况。

To summarize these are the rules: 总结这些是规则:

  1. Arguments, taken from Right to Left 论证,从右到左
    a. 一个。 Right Most 最正确的
    b. 2nd from Right 来自Right的第二名
  2. Base class 基类
  3. Virtual base 虚拟基地
  4. Base classes from Left to Right 从左到右的基类
  5. Members in Order of Declaration in class 成员在课堂上发表声明
  6. Constructor of called class 被调用类的构造函数

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM