有關虛擬函式(不能宣告的和需要極力避免的)
阿新 • • 發佈:2019-02-20
首先看不能宣告為virtual虛擬函式的情況:
- 普通函式(不能被覆蓋)
- 友元函式(C++不支援友元函式繼承)
- 行內函數(編譯期間展開,虛擬函式是在執行期間繫結)
- 建構函式(沒有物件不能使用建構函式,先有建構函式後有虛擬函式,虛擬函式是對物件的動作)
- 靜態成員函式(只有一份大家共享)
再看需要避免的情況:
-簡明概括:
先析構子類再析構父類,如果父類解構函式有虛擬函式,會導致呼叫子類的已經析構的內容。
先構造父親類再構造子類,如果父類建構函式有虛擬函式,會導致呼叫子類還沒構造的內容。
避免建構函式宣告為虛擬函式(如上)
所謂虛擬函式就是多型情況下只執行一個,而從繼承的概念來講,總是要先構造父類物件,然後才能是子類物件,如果建構函式設為虛擬函式,那麼當你在構造父類的建構函式時就不得不顯示的呼叫構造,還有一個原因就是為了防錯,試想如果你在子類中一不小心重寫了個跟父類建構函式一樣的函式,那麼你的父類的建構函式將被覆蓋,也即不能完成父類的構造.就會出錯.
避免建構函式中呼叫虛擬函式
在建構函式不要呼叫虛擬函式。在基類構造的時候,虛擬函式是非虛,不會走到派生類中,既是採用的靜態繫結。顯然的是:當我們構造一個子類的物件時,先呼叫基類的建構函式,構造子類中基類部分,子類還沒有構造,還沒有初始化,如果在基類的構造中呼叫虛擬函式,如果可以的話就是呼叫一個還沒有被初始化的物件,那是很危險的,所以C++中是不可以在構造父類物件部分的時候呼叫子類的虛擬函式實現。但是不是說你不可以那麼寫程式,你這麼寫,編譯器也不會報錯。只是你如果這麼寫的話編譯器不會給你呼叫子類的實現,而是還是呼叫基類的實現。
避免在解構函式中呼叫虛擬函式
在解構函式中也不要呼叫虛擬函式。在析構的時候會首先呼叫子類的解構函式,析構掉物件中的子類部分,然後在呼叫基類的解構函式析構基類部分,如果在基類的解構函式裡面呼叫虛擬函式,會導致其呼叫已經析構了的子類物件裡面的函式,這是非常危險的。
但是解構函式應該宣告為虛的,因為需要動態繫結,從而析構掉子類中新增加的內容。