参考文章:
一. 理论
1. 构造函数和析构函数
①构造函数
- 构造函数不能有返回值
- 缺省构造函数时,系统将自动调用该缺省构造函数初始化对象,缺省构造函数会将所有数据成员都初始化为零或空
- 创建一个对象时,系统自动调用构造函数
②析构函数
- 析构函数没有参数,也没有返回值。不能重载,也就是说,一个类中只可能定义一个析构函数
- 如果一个类中没有定义析构函数,系统也会自动生成一个默认的析构函数,为空函数,什么都不做
- 调用条件:1.在函数体内定义的对象,当函数执行结束时,该对象所在类的析构函数会被自动调用;2.用new运算符动态构建的对象,在使用delete运算符释放它时。
③拷贝构造函数
- 拷贝构造函数实际上也是构造函数,具有一般构造函数的所有特性,其名字也与所属类名相同。拷贝构造函数中只有一个参数,这个参数是对某个同类对象的引用。它在三种情况下被调用:
- 用类的一个已知的对象去初始化该类的另一个对象时;
- 函数的形参是类的对象,调用函数进行形参和实参的结合时;
- 函数的返回值是类的对象,函数执行完返回调用者。
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
*/