C++构造函数和析构函数顺序

标签 c++ constructor destructor

我正在尝试有关基类和成员构造和销毁的代码,但我对构造函数和析构函数的某些顺序感到困惑, 这段代码的输出是:

Base1 constructor
Member1 constructor
Member2 constructor
Derived1 constructor
Member3 constructor
Member4 constructor
Derived2 constructor
Derived2 destructor
Member4 destructor
Member3 destructor
Derived1 destructor
Member2 destructor
Member1 destructor
Base1 destructor

看前四行, 但我觉得顺序应该是

Base1 constructor
Derived1 constructor
Member1 constructor
Member2 constructor

谁能给我解释一下?

#include "stdafx.h"
#include <fstream>
using namespace std;
ofstream out("order.out");

#define CLASS(ID) class ID { \
public: \
  ID(int) { out << #ID " constructor\n"; } \
  ~ID() { out << #ID " destructor\n"; } \
};

CLASS(Base1);
CLASS(Member1);
CLASS(Member2);
CLASS(Member3);
CLASS(Member4);

class Derived1 : public Base1 {
  Member1 m1;
  Member2 m2;
public:
  Derived1(int) : m2(1), m1(2), Base1(3) {
    out << "Derived1 constructor\n";
  }
  ~Derived1() {
    out << "Derived1 destructor\n";
  }
};

class Derived2 : public Derived1 {
  Member3 m3;
  Member4 m4;
public:
  Derived2() : m3(1), Derived1(2), m4(3) {
    out << "Derived2 constructor\n";
  }
  ~Derived2() {
    out << "Derived2 destructor\n";
  }
};

int main() {
  Derived2 d2;
} ///:~

最佳答案

构造函数在层次结构中向上调用:

- base class member objects
- base class constructor body
- derived class member objects
- derived class constructor body

输出是正确的。

让我们简化您的代码:

struct BaseMember
{
   BaseMember() { cout << "base member" <<endl; }
};
struct Base
{
   BaseMember b;
   Base() { cout << "base" << endl; }
};
struct DerivedMember
{
   DerivedMember() { cout << "derived member" << endl; }
};
struct Derived : public Base
{
   DerivedMember d;
   Derived() { cout << "derived" << endl; }
};

Derived d;

创建d时,会先创建Base部分。在进入构造函数体之前,所有的成员对象都被初始化。所以 BaseMember 是第一个初始化的对象。

接下来,进入Base的构造函数。

Derived的构造函数进入之前,初始化了Derived的成员对象,所以创建了DerivedMember,接下来是Derived 构造函数被调用。

出现这种情况是因为当你进入派生类的构造函数体时,基类和成员对象必须完全初始化。

编辑 正如 Matthieu 所指出的,成员对象的初始化顺序是由它们在类定义中出现的顺序指定的,而不是它们在初始化列表中出现的顺序.

关于C++构造函数和析构函数顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9889145/

相关文章:

c++ - 迭代时如何知道我在树的末尾?

c++ - C++中的批处理文件命令

c# - 检查构造函数是否调用另一个构造函数

perl - 在Perl中,创建与程序包同名的子例程是否有害?

c++ - 返回的返回类型是对象的引用?

c++ - 递归:理解(子集和)包含/排除模式

c++ - 类型转换长指针问题

java - 获得此输出的可能原因是什么?

c++ - 内部类析构函数在基类析构函数之后调用

qt - 当删除其中一个类时,Qt中的信号是否会自动断开