絕不在構造和析構過程中呼叫虛函式

2021-08-19 16:42:06 字數 2222 閱讀 8163

一、中心內容

因為類呼叫從不下降至派生類,導致若為純虛函式,則找不到函式的實現**;若為非虛函式,則可能會導致呼叫錯誤的函式版本。。。

二、內容簡介

考慮這樣一系列繼承:

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...