effective C++ 筆記:條款09 決不在構(gòu)造和析構(gòu)過程中調(diào)用virtual函數(shù)

考慮以下代碼

class base {
public:
    base() :num(0){
        log();
    }
    virtual void log() {
        num++;
        numsta++;
    }
    int num;
    static  int numsta;
};

int base::numsta = 0;

class derived1:public base {
public:
    derived1() : num(0) {
    }
    virtual void log() {
        num++;
    }
    void fun() {
        cout << num<<endl;
    }
    int num;
};

class derived2:public base {
public:
    derived2() : num(0) {
    }
    virtual void log() {
        num++;
    }
    void fun() {
        cout << num<<endl;
    }
    int num;
};

int main(){
    derived1* d = new derived1;
    derived2* e = new derived2;
    base* p = dynamic_cast<base*>(d);
    base* q = dynamic_cast<base*>(e);
    d->fun();
    e->fun();
    cout << p->num<<endl;
    cout << q->num << endl;
    cout << base::numsta;
    return 0;
}

最終的輸出是


image.png

將log()函數(shù)放入構(gòu)造函數(shù),本意是要記錄對應(yīng)的子類對象的個數(shù)。
但是我們可以看到前兩個輸出,也就是說兩個子類中的num值并沒有被修改。
再看numsta的值被修改為2,也就是說構(gòu)造函數(shù)內(nèi)調(diào)用的log()是基類的版本。
實際上,基類構(gòu)造期間虛函數(shù)絕不會下降到子類階層,有種說法比較傳神:在基類構(gòu)造期間,虛函數(shù)并不是虛函數(shù)。
也可以換一個角度理解:構(gòu)造子類對象時,首先會調(diào)用基類構(gòu)造函數(shù),如果此時調(diào)用的虛函數(shù)下降到子類階層,并且子類虛函數(shù)調(diào)用了子類的成員變量,然而這些變量其實并還沒有初始化!,所以C++不會讓我們這樣做。
實際上如果在基類構(gòu)造期間,使用dynamic_cast,你會發(fā)現(xiàn)這時候這個對象是基類類型的。
同樣,在析構(gòu)過程中,一旦執(zhí)行到了基類的析構(gòu)函數(shù),那么這個對象退化成了基類對象。
回頭看第三行和第四行的輸出,這兩個子類對象中,它們的基類部分里num的值都被修改為1,這是符合以上分析的。

但是有時候可能會不小心忽略了以上警告

base(){
    init();
}

void init(){
    log();
}

這樣的代碼可能會讓你不小心進入以上陷阱,所以在這一點上務(wù)必要小心。

有一種比較好的解決方法
就是將log函數(shù)定義為非虛函數(shù),并且子類構(gòu)造函數(shù)的初始化列表中使用基類名的形式,如

derived(): base(logString){}

然后讓基類的構(gòu)造函數(shù)接收這個logString,然后在基類構(gòu)造函數(shù)內(nèi)根據(jù)子類構(gòu)造函數(shù)傳來的參數(shù)來執(zhí)行存儲日志的操作。
也就是用這種方法,要記錄各個子類對象的個數(shù),存儲的變量就不能放在子類中了(如果是普通變量),可以聲明為static變量,或者使用全局變量。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容