在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):
分析輸出結果,我們可以看到,在主函數中是首先建立了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();
}
編譯執行的結果如下:
這次我們看到,由于是先建立了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();
}
編譯執行的結果如下:
通過輸出結果,我們可以看到,先執行了Car1類的構造函數,後執行了Driver1類的構造函數,而在最後,則是先執行了Driver1類的析構函數,後執行了Car1類的析構函數,也就是說,不同的類依然是符合上述法則的。
上述例子較為簡單,而在實際應用中,主函數中可能遠比上述程式複雜的多,可能會執行更多的類操作,這樣就需要我們去時刻注意一下這條法則,避免出現一些看起來很“莫名其妙”的錯誤。