一、中心內容
因為類呼叫從不下降至派生類,導致若為純虛函式,則找不到函式的實現**;若為非虛函式,則可能會導致呼叫錯誤的函式版本。。。
二、內容簡介
考慮這樣一系列繼承:
class transaction{
public:
transaction();
virtual void logtransaction() const = 0;//每建立乙個交易物件,在審計日誌中需要建立一筆適當記錄,由此函式實現
transaction::transaction()
......
logtranction();
class buytranction: public transaction{
public:
virtual void logtransaction() const;
......
class selltranction : public transaction{
public:
virtual void logtransaction() const;
......
note:
執行語句:buytransaction b; 時發生的事情:
(1)派生物件內的基類成分會在派生自身成分被構造之前先構造妥當;
(2)紅色語句被呼叫的是transaction內的版本,不是buytransaction的版本!!!!!!
(3)即,在基類構造期間, 虛函式不是虛函式,不會下降到派生類階層。
(4)或者說,派生類的基類部分構造期間,物件的型別是基類而不是派生類!!!!!!
具體原因:
因為基類建構函式執行時,派生類的成員變數尚未初始化,若下降到派生階層,必然會用到區域性成員變數,但是這些變數尚未初始化,會出現錯誤。
針對紅色語句部分,基類構造函式呼叫了虛函式,這是不被允許的,具體原因:
1、純虛函式
由於一般情況下,純虛函式在基類中是不做定義的,所以呼叫的時候會找不到函式的定義**,不管是基類建構函式還是派生類建構函式構造基類成分時;
2、非純虛函式
原本構造乙個派生類物件需要呼叫的是派生類版本的logtransaction(),但是由於基類的建構函式中呼叫了基類版本的
logtransaction(),所以構造基類成分時, 會呼叫該版本,造成錯誤版本的呼叫。
解決辦法:
將基類的相應虛函式改為非虛函式,然後要求派生類建構函式傳遞必要資訊給基類的建構函式,然後基類的建構函式就可以安全地呼叫非虛函式。具體例項如下:
class transaction{
public:
explicit transaction(const std::string& loginfo);
void logtransaction(const std::string& loginfo) const;//去掉了虛函式屬性,使得整個繼承中只有乙個版本的此函式
......
transaction::transaction(const std::string& loginfo)
......
logtransaction(loginfo);
class buytransaction: public transaction{
public:
buytransaction(parameters)
:transaction(createlogstring (parameters))
private:
staticstd::string createlogstring(parameters);
note:
1、紅色部分就是派生類為基類建構函式提供的必要的logtransaction資訊;
2、綠色部分的私有成員之所以定義為靜態成員,在於靜態成員函式不包含this指標,這樣就不會指向其他尚未初始化的成員變數,避免了構造基類成分是出現錯誤。
note:
最重要的是!!!
因為使用非純虛函式會使得在構造派生物件時,建立基類成分過程中,呼叫基類版本的虛函式導致錯誤,不能實現向下呼叫!!!
所以,在派生類中建立這麼乙個私有靜態函式,增加可讀性,因為是static又不會包含this指標指向派生類中未初始化的成員變數,向上傳遞因類而異的不同的構造資訊給基類成分的建構函式,這樣就不會呼叫錯虛函式。。
Item 9 絕不在構造和析構過程中呼叫虛函式
這個應該是c 面試的經典題了,所以值得拿出來說一說 比如在乙個繼承體系中,基類的建構函式中呼叫了乙個基類的成員函式,你把它宣告為virtual,至少你在設計的時候是認為它有virtual屬性的。class base base base class derivedone public base cla...
不在構造和析構過程中呼叫虛函式
1.不能在構造過程中呼叫虛函式。比如 在基類中有乙個虛函式。class transaction transaction transaction 基類建構函式實現 下面有兩個派生類繼承它 class buytransaction public transaction class selltransac...
C 箴言 絕不在構造或析構期呼叫虛函式
文章內容請參加 以下是我自己寫的乙個測試用的例子 test.h ifndef test h define test h include class base protected virtual void init class inherit public base protected void in...