構造函數及析構函數與虛函數的關係

我們都知道構造函數不能爲虛函數,而基類的析構函數一般都要定義爲虛函數。今天重新複習了一下,特在此記載,以便查找。


構造函數不能爲虛函數主要有以下兩點

1、必要性分析:
當定義派生類對象時,它會主動依次調用構造函數,順序爲基類的構造函數->一級派生類構造函數->二級派生類構造函數….直到當前派生類的構造函數調用完畢爲止,到此派生類對象生成。
而虛函數存在的意義爲動態綁定,從上一段話可知,它會從基類開始依次自動調用相應的構造函數,根本就不存在動態綁定的必要。
2、內存角度分析:
構造函數的作用是生成相應的類對象。虛函數的動態綁定是依據一張虛函數表來確認的最終綁定到哪一個虛函數版本。
而調用構造函數之前,我們對類對象所做的操作僅限於分配內存,還沒有對內存進行初始化。此時,內存空間上也不存在虛函數表,因此,按照這樣的執行順序,虛函數的動態綁定是實現不了的。


基類析構函數與虛函數的關係

如果類的數據成員中不存在成員(指針)與動態分配的內存相關聯,我們一般不用自己定義析構函數,而是採用默認的析構函數析構類對象。一旦與動態分配的內存相關聯,爲了防止內存泄露,我們需要自己定義析構函數,手動釋放動態分配的內存。

三法則:如果一個類需要析構函數,幾乎也需要定義賦值構造函數和重載賦值操作符。

在分析基類析構函數爲什麼要定義爲虛析構函數之前,我們要先明白虛函數存在的意義就是爲了動態綁定,實現面向對象的特性之一 :多態。

我們知道通過基類的指針或者引用可以實現對虛函數的動態綁定,那麼當我們通過一個基類指針或者引用來析構一個對象時,我們是無法判斷基類現在綁定的對象是基類還是派生類,如果析構函數不是虛函數,那麼基類指針只會調用基類的析構函數,如此就發生了一些不該發生的事。只有將析構函數定義爲虛函數,才能通過動態綁定,調用對應的析構函數版本,正確的析構類對象。

可以這麼說:任何class只要有virtual函數都幾乎確定也要有一個virtual析構函數(引用自Effective C++ 條款7)

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