13.析構函數一般寫成虛函數的原因、構造函數爲什麼一般不定義爲虛函數、構造函數或者析構函數中調用虛函數會怎樣

綜合解答https://www.cnblogs.com/lpxblog/p/5890933.html

基類的析構函數爲什麼必須是虛函數呢?

  • 我們都知道,想要回收一個對象申請的資源,那麼就需要調用析構函數。雖然我們沒有顯示地調用析構函數,但是編譯器都會默認地爲我們執行析構函數。

  • 那麼當我們執行 BaseClass *base = new BaseClass(); 當我們執行 delete base時,會調用析構函數爲我們釋放資源。而 我們執行BaseClass *sub = new SubClass(); 如果BaseClass基類的析構函數不是虛函數的時候,delete sub 對象的時候,只會釋放BaseClass 基類申請的資源,而不是釋放SubClass派生類的資源。原因如下:

  • 基類指針指向了派生類對象,而基類中的析構函數是非virtual的,而虛構函數是動態綁定的基礎。現在析構函數不是virtual的,因此不會發生動態綁定,而是靜態綁定,指針的靜態類型爲基類指針,因此在delete的時候只會調用基類的析構函數,而不會調用派生類的析構函數。這樣,在派生類中申請的資源就不會得到釋放,就會造成內存泄漏,這是相當危險的:如果系統中有大量的派生類對象被這樣創建和銷燬,就會有內存不斷的泄漏,久而久之,系統就會因爲缺少內存而崩潰。

  • 當然,如果在派生類中沒有動態申請有資源的時候,是不會造成內存泄漏的。而當派生類對象的析構函數中有內存需要回收,並且在編程過程中採用了基類指針指向派生類對象,如爲了實現多態,並且通過基類指針將對象銷燬,這時,就會因爲基類的析構函數爲非虛函數而不觸發動態綁定,從而沒有調用派生類的析構函數而導致內存泄漏。

  • 因此,爲了防止這種情況下的內存泄漏的發生,最後將基類的析構函數寫成virtual虛析構函數。

C++的構造函數爲何不能爲虛函數

  1. 存儲空間角度:虛函數對應一個vtable,vtable存儲於對象的內存空間
    若構造函數是虛的,則需要通過 vtable來調用,若對象還未實例化,即內存空間還沒有,無法找到vtable

  2. 使用角度:虛函數主要用於在信息不全的情況下,能使重載的函數得到對應的調用。
    構造函數本身就是要初始化實例,那使用虛函數就沒有實際意義

  3. 從實際含義上看,在調用構造函數時還不能確定對象的真實類型(因爲子類會調父類的構造函數);而且構造函數的作用是提供初始化,在對象生命期只執行一次,不是對象的動態行爲,也沒有太大的必要成爲虛函數

構造函數或者析構函數中調用虛函數會怎樣https://www.cnblogs.com/vincently/p/4754206.html
構造函數中調用虛函數單補解析https://blog.csdn.net/magictong/article/details/6734241

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