C++构造函数和析构函数的调用顺序

简介:

1、构造函数的调用顺序 

基类构造函数、对象成员构造函数、派生类本身的构造函数  

2、析构函数的调用顺序

派生类本身的析构函数、对象成员析构函数、基类析构函数(与构造顺序正好相反) 

3、特例 

局部对象,在退出程序块时析构

静态对象,在定义所在文件结束时析构

全局对象,在程序结束时析构 

继承对象,先析构派生类,再析构父类 

对象成员,先析构类对象,再析构对象成员

4、例子 

复制代码
复制代码
#include <iostream>
using namespace std;

class Base1
{
public: Base1(void){cnt++;cout<<"Base1::constructor("<<cnt<<")"<<endl;} ~Base1(void){cnt--;cout<<"Base1::deconstructor("<<cnt + 1<<")"<<endl;} private: static int cnt; }; int Base1::cnt = 0; class Base2 { public: Base2(int m){num = m; cout<<"Base2::constructor("<<num<<")"<<endl;} ~Base2(void){cout<<"Base2::deconstructor("<<num<<")"<<endl;} private: int num; }; class Example { public: Example(int n){num = n; cout<<"Example::constructor("<<num<<")"<<endl;} ~Example(void){cout<<"Example::deconstructor("<<num<<")"<<endl;} private: int num; }; class Derived:public Base1, public Base2 { public: Derived(int m, int n):Base2(m),ex(n){cnt++;cout<<"Derived::constructor("<<cnt<<")"<<endl;} ~Derived(void){cnt--;cout<<"Derived::deconstructor("<<cnt+1<<")"<<endl;} private: Example ex; static Example stex; //Example::constructor(1) //不能输出 static int cnt; }; int Derived::cnt = 0; Derived ge_a(1,2); // Base1::constructor(1) // Base2::constructor(1) // Example::constructor(2) // Derived::constructor(1) static Derived gs_b(3,4); // Base1::constructor(2) // Base2::constructor(3) // Example::constructor(4) // Derived::constructor(2) int main(void) { cout << "---------start---------" << endl; Derived d(5,6); // Base1::constructor(3) // Base2::constructor(5) // Example::constructor(6) // Derived::constructor(3) Derived e(7,8); // Base1::constructor(4) // Base2::constructor(7) // Example::constructor(8) // Derived::constructor(4) cout << "----------end----------" << endl; //Derived e(7,8) 析构 // Derived::deconstructor(4) // Example::deconstructor(8) // Base2::deconstructor(7) // Base1::deconstructor(4) //Derived d(5,6) 析构 // Derived::deconstructor(3) // Example::deconstructor(6) // Base2::deconstructor(5) // Base1::deconstructor(3) return 0; } //static Derived gs_b(3,4) 析构 // Derived::deconstructor(2) // Example::deconstructor(4) // Base2::deconstructor(3) // Base1::deconstructor(2) //Derived ge_a(1,2) 析构 // Derived::deconstructor(1) // Example::deconstructor(2) // Base2::deconstructor(1) // Base1::deconstructor(1) //static Example stex 析构 //Example::deconstructor(1) //不能输出 
复制代码
复制代码

 

复制代码
复制代码
#include <iostream>
using namespace std;
class A
{
public: A(){cout<<"A::constructor"<<endl;}; ~A(){cout<<"A::deconstructor"<<endl;}; }; class B { public: B(){cout<<"B::constructor"<<endl;}; ~B(){cout<<"B::deconstructor"<<endl;}; }; class C : public A { public: C(){cout<<"C::constructor"<<endl;}; ~C(){cout<<"C::deconstructor"<<endl;}; private: // static B b;  B b; }; class D : public C { public: D(){cout<<"D::constructor"<<endl;}; ~D(){cout<<"D::deconstructor"<<endl;}; }; int main(void) { C* pd = new D(); delete pd; return 0; } /* Output ----->B b A::constructor B::constructor C::constructor D::constructor C::deconstructor B::deconstructor A::deconstructor ----->static B b A::constructor C::constructor D::constructor C::deconstructor A::deconstructor */
复制代码
复制代码
相关文章
|
10月前
|
存储 编译器 C++
【c++】类和对象(下)(取地址运算符重载、深究构造函数、类型转换、static修饰成员、友元、内部类、匿名对象)
本文介绍了C++中类和对象的高级特性,包括取地址运算符重载、构造函数的初始化列表、类型转换、static修饰成员、友元、内部类及匿名对象等内容。文章详细解释了每个概念的使用方法和注意事项,帮助读者深入了解C++面向对象编程的核心机制。
254 5
|
10月前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
553 4
|
12月前
|
编译器 C++
C++ 类构造函数初始化列表
构造函数初始化列表以一个冒号开始,接着是以逗号分隔的数据成员列表,每个数据成员后面跟一个放在括号中的初始化式。
196 30
|
11月前
|
编译器 C语言 C++
C++入门4——类与对象3-1(构造函数的类型转换和友元详解)
C++入门4——类与对象3-1(构造函数的类型转换和友元详解)
96 2
|
11月前
|
C++
C++构造函数初始化类对象
C++构造函数初始化类对象
85 0
|
11月前
|
C++
C++入门4——类与对象3-2(构造函数的类型转换和友元详解)
C++入门4——类与对象3-2(构造函数的类型转换和友元详解)
107 0
|
C++ 运维
开发与运维函数问题之析构函数在C++类中起什么作用如何解决
开发与运维函数问题之析构函数在C++类中起什么作用如何解决
89 11
|
编译器 C++
C++的基类和派生类构造函数
基类的成员函数可以被继承,可以通过派生类的对象访问,但这仅仅指的是普通的成员函数,类的构造函数不能被继承。构造函数不能被继承是有道理的,因为即使继承了,它的名字和派生类的名字也不一样,不能成为派生类的构造函数,当然更不能成为普通的成员函数。 在设计派生类时,对继承过来的成员变量的初始化工作也要由派生类的构造函数完成,但是大部分基类都有 private 属性的成员变量,它们在派生类中无法访问,更不能使用派生类的构造函数来初始化。 这种矛盾在C++继承中是普遍存在的,解决这个问题的思路是:在派生类的构造函数中调用基类的构造函数。 下面的例子展示了如何在派生类的构造函数中调用基类的构造函数:
119 1
|
编译器 C++
【C++】详解构造函数
【C++】详解构造函数
|
存储 编译器 C++
【C++】类和对象④(再谈构造函数:初始化列表,隐式类型转换,缺省值
C++中的隐式类型转换在变量赋值和函数调用中常见,如`double`转`int`。取引用时,须用`const`以防修改临时变量,如`const int& b = a;`。类可以有隐式单参构造,使`A aa2 = 1;`合法,但`explicit`关键字可阻止这种转换。C++11起,成员变量可设默认值,如`int _b1 = 1;`。博客探讨构造函数、初始化列表及编译器优化,关注更多C++特性。