構造函數不能聲明爲虛函數, 析構函數可以

構造函數不能聲明爲虛函數, 析構函數可以

  1. 在構造一個對象的時候,必須要知道對象的實際類型,而虛函數是在執行期才能確定實際的對象類型,在構造對象的時候,由於此時對象還沒有構建成功,編譯器無法知道該對象的實際類型,是該類本身還是該類的一個派生類
  2. 另外,虛函數都是通過虛函數表來調用的,而class object的虛函數表一般都是在構造函數中才會被賦值,即初始化vptr讓它指向正確的虛函數表。那在構造期間,vptr還沒有被初始化,故無法調用到虛函數。

根據上面的兩點原因,故構造函數不能聲明爲虛函數

那麼爲什麼析構函數通常就要設置爲虛函數呢?

在類的繼承中,如果有基類指針指向派生類對象,那麼用基類指針delete時,如果不把析構函數定義成虛函數的話,那麼就會直接釋放base object部分,而派生類自己的那部分內容就無法釋放掉,造成memory leak。

關於構造函數和析構函數的注意點:

  1. 如果我們定義了一個構造函數,編譯器就不會再爲我們生成默認構造函數了
  2. 編譯器生成的析構函數是非虛的,除非是一個子類、其父類有個虛析構,此時的析構函數虛特性來自父類
  3. 有虛函數的類,幾乎可以確定要有一個虛析構函數
  4. 如果一個類不可能是基類就不要申明析構函數爲虛函數,虛函數需要額外的空間負擔
  5. 析構函數的異常退出會導致析構函數執行不完全,從而會有內存泄漏的問題
  6. 在構造函數中不要調用虛函數。在基類構造的時候,虛函數式非虛,不會走到派生類中,既是採用的靜態綁定。當我們構造一個子類的對象時,先調用基類的構造函數,構造子類中基類部分,子類還沒有構造,還沒有初始化,如果在基類的構造中調用了虛函數,那麼就是調用一個還沒有被初始化的對象,所以C++不可以在構造父類對象的時候調用子類的虛函數實現。如果你這麼寫的話就是調用的基類的函數實現而不是子類的函數實現。
  7. 在析構函數中也不要調用虛函數。在析構的時候會首先調用子類的析構函數,析構掉對象中的子類部分,然後調用基類的析構函數析構基類部分。如果在基類的析構函數裏調用虛函數,會導致其調用已經析構了的子類對象裏面的函數,這是錯誤的
  8. 在設計派生類的拷貝函數時,需要記住調用基類的拷貝函數來拷貝基類的部分。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章