构造、析构顺序
在C++中,类对象的初始化和析构顺序是由其继承关系和成员变量的声明顺序决定的。理解这一点对于确保资源的正确管理和避免潜在的内存泄漏至关重要。
# 一、初始化顺序
初始化顺序是指对象创建时,构造函数调用的顺序。这个顺序分为以下几部分:
基类构造函数:在派生类的构造函数执行之前,首先调用基类的构造函数。基类构造函数按照继承层次自上而下依次调用。
成员对象的构造函数:基类构造函数执行完毕后,按照成员对象在类中声明的顺序依次调用这些成员对象的构造函数。
派生类构造函数:最后,执行派生类的构造函数。
# 示例:
#include <iostream>
class Base {
public:
Base() {
std::cout << "Base Constructor" << std::endl;
}
~Base() {
std::cout << "Base Destructor" << std::endl;
}
};
class Member {
public:
Member() {
std::cout << "Member Constructor" << std::endl;
}
~Member() {
std::cout << "Member Destructor" << std::endl;
}
};
class Derived : public Base {
Member m;
public:
Derived() {
std::cout << "Derived Constructor" << std::endl;
}
~Derived() {
std::cout << "Derived Destructor" << std::endl;
}
};
int main() {
Derived d;
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
输出结果:
Base Constructor
Member Constructor
Derived Constructor
Derived Destructor
Member Destructor
Base Destructor
1
2
3
4
5
6
2
3
4
5
6
解释:
- 首先调用
Base
类的构造函数。 - 然后按照声明顺序调用
Member
成员对象的构造函数。 - 最后调用
Derived
类的构造函数。
# 二、析构顺序
析构顺序与初始化顺序相反:
派生类析构函数:首先调用派生类的析构函数。
成员对象析构函数:然后按照声明顺序的逆序调用成员对象的析构函数。
基类析构函数:最后调用基类的析构函数。
在上面的例子中,析构函数的调用顺序是:
Derived
类的析构函数。Member
成员对象的析构函数。Base
类的析构函数。
# 总结
- 初始化顺序:基类 -> 成员对象 -> 派生类。
- 析构顺序:派生类 -> 成员对象 -> 基类。
注意:
- 成员对象的初始化顺序与它们在类中被声明的顺序一致,而不是在构造函数初始化列表中的顺序。这意味着即使在构造函数中按照不同顺序初始化成员变量,它们也会按照声明顺序进行初始化。
- 正确理解这些顺序有助于编写健壮的C++代码,避免资源管理中的潜在错误。
编辑 (opens new window)
上次更新: 2024/09/13, 11:59:12