c++的多型性是通過虛函式來實現的,虛函式的出現使得動態鏈結成為可能。
基於建構函式的特點,不能將建構函式定義為虛函式,但可以將析構函式定義為虛函式。
一般情況:當派生類的物件從記憶體中撤銷時,會先呼叫派生類的析構函式,然後自動呼叫基類的析構函式,如此看來析構函式也沒有必要定義為虛函式。
但 如考慮如下這種情況,如果使用基類指標指向派生類的物件,而這個派生類物件恰好是用new運算建立的,這種情況下會如何呢?當程式使用delete運算撤銷派生類物件時,這時只會呼叫基類的析構函式,而沒有呼叫派生類的析構函式。如果使用的是虛析構函式的話,就不一樣了,所以定義虛析構函式有時候還是很有必要的。
我們知道,用c++開發的時候,用來做基類的類的析構函式一般都是虛函式。可是,為什麼要這樣做呢?下面用乙個小例子來說明:
有下面的兩個類:
class
clxbase
;virtual
~clxbase() {};
virtual
void
dosomething() ;
};class
clxderived :
public
clxbase;~
clxderived() ;
void
dosomething() ;};
**clxbase
*ptest
=new
clxderived;
ptest
->
dosomething();
delete ptest;
的輸出結果是:
do something in class clxderived!
output from the destructor of class clxderived!
這個很簡單,非常好理解。
但是,如果把類clxbase析構函式前的virtual去掉,那輸出結果就是下面的樣子了:
do something in class clxderived!
也就是說,類clxderived的析構函式根本沒有被呼叫!一般情況下類的析構函式裡面都是釋放記憶體資源,而析構函式不被呼叫的話就會造成記憶體洩漏。我想所有的c++程式設計師都知道這樣的危險性。當然,如果在析構函式中做了其他工作的話,那你的所有努力也都是白費力氣。
所以,文章開頭的那個問題的答案就是--這樣做是為了當用乙個基類的指標刪除乙個派生類的物件時,派生類的析構函式會被呼叫。
當然,並不是要把所有類的析構函式都寫成虛函式。因為當類裡面有虛函式的時候,編譯器會給類新增乙個虛函式表,裡面來存放虛函式指標,這樣就會增加類的儲存空間。所以,只有當乙個類被用來作為基類的時候,才把析構函式寫成虛函式。
note:可見,子型別化要求將析構函式宣告為虛函式。特別是當析構函式完成了一些有意義的操作時,例如,關閉檔案、刪除指標所指向的物件等。總之,將析構函式宣告為虛函式一般沒有什麼壞處,所以,如果不能決定是否應當將析構函式宣告為虛函式時,就將析構函式宣告為虛函式。
建構函式不能被宣告為虛函式。因為對建構函式的呼叫意味著要建立乙個物件,這時,必須要確切地知道這個物件的型別,而且我們也不會為乙個已存在的物件呼叫建構函式,因此,將建構函式宣告為虛函式是沒有意義的。
基類虛析構函式
why虛析構函式?主要還是由於基類指標或引用可以不進行顯示型別轉換的情況下指向派生類物件。同時通過引用或者指標或引用呼叫方法時遵循 例如 定義了基類brass,派生類brassplus 如果viewacct 不是虛方法,則b1 ref.viewacct 和b2 ref.viewacct 均是使用br...
基類虛析構函式分析
多型是由虛函式表來實現,通過父類指標來實現動態繫結。子類重寫父類的虛函式後,覆蓋虛函式表中父類該虛函式在表中原來的位置,也許 覆蓋 也就是由此得稱。那析構函式是否也如此呢?程式 中經常可以見到將基類的析構函式寫成虛函式,目的就是為了防止由以下這種情況造成的記憶體洩漏 class a class b ...
多型基類與虛析構函式
假設我們有乙個基類a,很不幸的,a的析構函式是乙個non virtual。同時我們有乙個派生類b,它派生自a。我們定義了乙個a型別指標,它指向的實際物件是b a ptr new b 然後在程式的某處,我們不再需要b了,我們將指標ptr delete掉 delete ptr 注意new永遠要和dele...