為什麼要用虛析構函式

2021-07-03 20:20:02 字數 1266 閱讀 9925

1 問題引出:為什麼要使用虛析構函式?

class a //父親

};int main()

我們知道在delete p; 中 delete 操作符,會呼叫物件的析構函式,但是這裡傳入的是父類物件指標,所以delete 此時並不知道應該呼叫哪個析構函式,保險起見則只呼叫父類的析構函式,也就是說如果沒有使用虛析構函式,那麼一般情況下只會去析構父類,而不會去析構子類。所以當delete p; 的時候,就會發生記憶體洩漏,也從而產生了異常。
注:上面是傳入父類指標並對其直接析構,如果不是對父類指標(或者引用)直接析構那一般不會出錯,如 void main() 這時雖然使用了父類指標,但不是對父類指標析構,而是很明確直接析構b,所以用不用虛函式,也可以正確析構,

如果某個類不包含虛函式,那一般是表示它將不作為乙個基類來使用。當乙個類不準備作為基類使用時,使析構函式為虛一般是個壞主意。因為它會為類增加乙個虛函式表,使得物件的體積翻倍,還有可能降低其可移植性。

所以基本的一條是:無故的宣告虛析構函式和永遠不去宣告一樣是錯誤的。實際上,很多人這樣總結:當且僅當類裡包含至少乙個虛函式的時候才去宣告虛析構函式。

2 那使用虛析構函式會有什麼效果?

我們把析構函式前加上virtual關鍵字,來看一下效果。

class a //父親

};int main()

在使用虛析構函式後,delete 明顯變聰明了,知道應該先析構兒子,再去析構父親了。但是在b類(兒子類)的析構函式刻意沒有加 virtual 關鍵字,可見如同其他虛函式一樣,只要父類加 virtual 就可以了。

引申:

虛析構函式,也是通過vftable來實現的,實際上當父類的析構函式宣告為虛函式時,子類的析構函式也變成了虛函式(雖然兩者函式名不同),即告訴編譯器,我和我的派生類都需要動態(執行時)完成析構函式執行。

在編譯器中我們可以看到:

析構函式的名字做了特殊處理,換成了『vector deleting destructor』,用特定的標記,來標明析構函式。所以即使函式名不同,只要父類中使用 virtual ,也可以是所有子類的析構函式變成虛函式。

注: 為了方便對比,現給出包含多個虛函式的虛函式表,如下:

為什麼需要虛析構函式

這樣做是為了當用乙個基類的指標刪除乙個派生類的物件時,派生類的析構函式會被呼叫。class clxbase virtual clxbase virtual void dosomething class clxderived public clxbase clxderived void dosomet...

C 析構函式為什麼要為虛函式

1.為什麼基類的析構函式是虛函式?在實現多型時,當用基類操作派生類,在析構時防止只析構基類而不析構派生類的狀況發生。下面 網路 源位址 a.第一段 includeusing namespace std class clxbase clxbase void dosomething class clxd...

C 析構函式為什麼要為虛函式

注 本文內容 於zhice163博文,感謝作者的整理。1.為什麼基類的析構函式是虛函式?在實現多型時,當用基類操作派生類,在析構時防止只析構基類而不析構派生類的狀況發生。下面 網路 源位址 a.第一段 includeusing namespace std class clxbase clxbase ...