Effective C++ 條款09 絕不在構造和析構過程中呼叫virtual函式
本條款的內容主要講述了在子類和父類之間的構造和析構階段不要去呼叫virtual函式,因為那可能會和你預想的結果有出入。
class Transportion
{
Transportion();
virtual void logTransction()const = 0;//純虛擬函式
};
Transportion::Transportion()
{
//........
logTransction();
}
class BuyTransction :public Transportion {
public:
virtual void logTransction() const;
//...........
};
class sellTransction :public Transportion
{
public:
};
現在當 BuyTransction b;執行會發生什麼?
答:無疑會有一個BuyTransction建構函式被呼叫,但首先Transction建構函式一定會更早呼叫;因為建構函式的呼叫順序是從最內層的階段開始的,解構函式則相反。Transction建構函式的最後一行呼叫virtual函式logTransction,問題出現了——這時候呼叫的logTransction並不是BuyTransction版本的而是Transction的,即使你建立的是一個BuyTransction物件。是的,基類構造期間virtual函式絕不會下掉到派生類的層次。取而代之的是物件的行為就像是隸屬基類型別一樣。
如果在基類構造期間呼叫的virtual函式下降到了派生類階層,而派生類的函式幾乎必然會用到local變數,而那些成員變數尚未初始化。這將會使你誤用物件未初始化的部分。
其根本原因:在派生類物件的基類構造期間物件的型別是基類而不是派生類。物件在派生類建構函式開始執行前不會成為一個派生類物件。