天天看點

C++多個類中構造函數與析構函數的調用順序

       在C++中有一個很重要的法則:使用構造函數建立對象的順序與使用析構函數釋放對象的順序相反。對于一些C++的初學者來說,這是一條有點費解的法則,那麼該怎麼了解和清晰的表現出來呢?下面我們通過程式來展現一下:

#include<iostream>
using namespace std;

//建立一個汽車類
class Car
{
public:
        //構造函數
	Car(short, int);
        //析構函數
	~Car();
	void move();
private:
	short speed;
	int num;
};

Car::Car(short s, int n)
{
	speed = s;
	num = n;
	cout << "建立第" << num << "輛車,速度是" << speed << " 米/秒" << endl;
}

Car::~Car()
{
	cout << "銷毀掉第 " << num << "輛車" << endl;
}

void Car::move()
{
	cout << "第 " << num << "輛車速度是" << speed << endl;
}

//主函數
void main()
{
        //先建立第car1對象,再建立car2對象
	Car car1(10, 1), car2(20, 2);
	car1.move();
	car2.move();
           
}
           

       編譯執行的結果如下(編譯環境為Visual Studio 2013):

C++多個類中構造函數與析構函數的調用順序
C++多個類中構造函數與析構函數的調用順序

       分析輸出結果,我們可以看到,在主函數中是首先建立了car1類,後建立了car2類,是以在執行構造函數的順序上,是先執行car1對象的構造函數,後執行car2對象的構造函數。而在主函數執行結束,要調用析構函數的時候,根據開始說的法則,則會先執行car2類的析構函數,後執行car1類的析構函數。這就是“使用構造函數建立對象的順序與使用析構函數釋放對象的順序相反”這條法則的一個很好的展現。

       那麼我們可以舉一反三,如果想先執行car1類的析構函數,後執行car2類的析構函數,那麼上述程式該如何修改呢?很簡單,依據上述法則,我們隻需要修改為先建立car2類,後建立car1類,就可以了。修改後的程式如下:

#include<iostream>
using namespace std;

class Car
{
public:
	Car(short, int);
	~Car();
	void move();
private:
	short speed;
	int num;
};

Car::Car(short s, int n)
{
	speed = s;
	num = n;
	cout << "建立第" << num << "輛車,速度是" << speed << " 米/秒" << endl;
}

Car::~Car()
{
	cout << "銷毀掉第 " << num << "輛車" << endl;
}

void Car::move()
{
	cout << "第 " << num << "輛車速度是" << speed << endl;
}

void main()
{
        //這次先建立car2類,後建立car1類
	Car car2(20, 2), car1(10, 1);
	car1.move();
	car2.move();
}
           

       編譯執行的結果如下:

C++多個類中構造函數與析構函數的調用順序

       這次我們看到,由于是先建立了car2類,後建立了car1類,是以先執行了car2類的構造函數,後執行car1類的構造函數;而在最後,會先執行car1類的析構函數,後執行car2類的西溝函數。

       當然。我們還可以再往深了想一想,上面這兩個例子都是基于同一個類來建立兩個對象的,那麼如果是兩個不同的類建立的對象呢?是否依然符合這條法則呢?我們再修改程式來驗證一下:

#include<iostream>
using namespace std;

//建立一個汽車類
class Car
{
public:
	Car(short, int);
	~Car();
	void move();
private:
	short speed;
	int num;
};

//建立一個司機類
class Driver
{
public:
	Driver(short);
	~Driver();
	void drive();
private:
	short years;
};

Car::Car(short s, int n)
{
	speed = s;
	num = n;
	cout << "建立第" << num << "輛車,速度是" << speed << " 米/秒" << endl;
}

Car::~Car()
{
	cout << "銷毀掉第 " << num << "輛車" << endl;
}

void Car::move()
{
	cout << "第 " << num << "輛車速度是" << speed << endl;
}

Driver::Driver(short y)
{
	cout << "我是一個" << y << "歲的司機" << endl;
}

Driver::~Driver()
{
	cout << "我要停車了" << endl;
}

void Driver::drive()
{
	cout << "我要開車了" << endl;
}

//主函數
void main()
{
        //先建立汽車類
	Car car1(10, 1);
        //後建立司機類
	Driver driver1(30);
	driver1.drive();
	car1.move();
}
           

       編譯執行的結果如下:

C++多個類中構造函數與析構函數的調用順序

       通過輸出結果,我們可以看到,先執行了Car1類的構造函數,後執行了Driver1類的構造函數,而在最後,則是先執行了Driver1類的析構函數,後執行了Car1類的析構函數,也就是說,不同的類依然是符合上述法則的。

       上述例子較為簡單,而在實際應用中,主函數中可能遠比上述程式複雜的多,可能會執行更多的類操作,這樣就需要我們去時刻注意一下這條法則,避免出現一些看起來很“莫名其妙”的錯誤。