C++ 構造函數和析構函數的調用順序、虛析構函數的作用

構造函數和析構函數的調用順序

構造函數的調用順序:

當建立一個對象時,首先調用基類的構造函數,然後調用下一個派生類的構造函數,依次類推,直至到達最底層的目標派生類的構造函數爲止。

析構函數的調用書序:

當刪除一個對象時,首先調用該派生類的析構函數,然後調用上一層基類的析構函數,依次類推,直到到達最頂層的基類的析構函數爲止。

簡單的說,構造函數是“自上向下”調用,析構函數是“自下而上”調用。

演示代碼如下:

#include<iostream>
using namespace std;

class Base{
public:
	Base(){cout<<"創建Base基類。"<<endl;}
	~Base() {cout<<"刪除Base基類。"<<endl;}
};
class Child : public Base{
public:
	Child() {cout<<"創建Child派生類。"<<endl;}
	~Child() {cout<<"刪除Child派生類。"<<endl;} 
};

int main()
{
	cout<<"*********構造函數調用順序示例***********"<<endl;
	Child *C1 = new Child;
	cout<<"*********析構函數調用順序示例***********"<<endl;
	delete C1;
}
運行結果如下圖:



虛析構函數的作用

通過基類的指針來刪除派生類的對象時,基類的析構函數應該是虛的。

原因:在公有繼承中,基類對派生類及其對象的操作,只能影響到那些從基類繼承下來的成員。如果想要用基類對非繼承成員進行操作,則要把基類的這個操作(函數)定義爲虛函數。析構函數同樣需要如此。

如果用基類的指針來刪除派生類的對象,而這個基類有一個非虛的析構函數,則結果是未定義的。後果是對象的派生部分不會被銷燬,然而,基類部分很可能已被銷燬,這就導致產生了“部分析構”的情況,這是一個內存泄露

可以通過如下代碼來說明:

#include<iostream>
using namespace std;

class Base{
public:
	Base(){cout<<"創建Base基類。"<<endl;}
	~Base() {cout<<"刪除Base基類。"<<endl;}	/*非虛析構函數*/
};
class Child : public Base{
public:
	Child() {cout<<"創建Child派生類。"<<endl;}
	~Child() {cout<<"刪除Child派生類。"<<endl;} 
};

int main()
{
	cout<<"*********非虛析構函數調用示例***********"<<endl;
	Base *C1 = new Child;
	delete C1;
}
運行結果如下,此時刪除C1指針時,只調用了Base類的析構函數,沒有調用Child類的析構函數。


當更改Base基類的析構函數爲虛函數時,代碼如下:

#include<iostream>
using namespace std;

class Base{
public:
	Base(){cout<<"創建Base基類。"<<endl;}
	virtual ~Base() {cout<<"刪除Base基類。"<<endl;}	/*虛析構函數*/
};
class Child : public Base{
public:
	Child() {cout<<"創建Child派生類。"<<endl;}
	~Child() {cout<<"刪除Child派生類。"<<endl;} 
};

int main()
{
	cout<<"*********虛析構函數調用示例***********"<<endl;
	Base *C1 = new Child;
	delete C1;
}
此時運行結果如下,先調用了Child派生類的析構函數,再調用了Base基類的析構函數。



但是,一般如果不做基類的類的析構函數一般不聲明爲虛函數,因爲虛函數的實現要求對象攜帶額外的信息,這些信息用於在運行時確定該對象應該調用哪一個虛函數。典型情況下,這一信息具有一種被稱爲 vptr(virtual table pointer,虛函數表指針)的指針的形式。vptr 指向一個被稱爲 vtbl(virtual table,虛函數表)的函數指針數組,每一個包含虛函數的類都關聯到 vtbl。當一個對象調用了虛函數,實際的被調用函數通過下面的步驟確定:找到對象的 vptr 指向的 vtbl,然後在 vtbl 中尋找合適的函數指針。這樣子會使類所佔用的內存增加。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章