1. 程式人生 > >關於C++派生類中建構函式呼叫順序的問題

關於C++派生類中建構函式呼叫順序的問題

    近期在網上搜尋了一下關於C++派生類建構函式的呼叫問題,大部分博文給出的順序是:

1、基類構造

2、成員構造

3、派生構造。

這個順序嚴格來講是錯誤的,對新手極具誤導性!

    依據侯捷翻譯的Stanley B. Lippman的<<深度探索C++物件模型>>一書(主要是其中5.2節“繼承體系下的物件構造”的敘述),對於一個派生類的建構函式,其中包含了基類構造、成員構造和自定義的程式碼等部分(忽略與本討論不太相關的this指標、虛擬函式表指標等),其程式碼安排順序為:

1、(虛繼承的)基類構造

2、(普通繼承的)基類構造

3、設定虛表指標

4、成員構造

5、自己寫的程式碼

真正生成的派生類的建構函式的形式如下:(忽略關於this指標、虛擬函式表指標的程式碼)

//CDerive為派生類,CVBase為虛繼承的基類,CBase為基類,member為CMember型別的成員

CDerive::CDerive()

{

    CVBase::CVBase();

    CBase::CBase();

    member.CMember::CMember();

    //自己的程式碼

}

由此可以看出,基類構造的呼叫是在派生構造之中而不是之後,派生構造的呼叫與基類構造的呼叫是包含關係而不是先後關係。對“函式呼叫”的理解通常是:跳轉到函式入口地址並執行其後的程式碼,若以此說來,真正的呼叫順序為:

1、派生構造

2、基類構造

3、成員構造

經除錯,實際的程式碼執行結果符合Lippman的描述,函式呼叫的堆疊順序:

1、派生構造進入

2、基類構造進入

3、基類構造返回

4、成員構造進入

5、成員構造返回

6、派生構造返回

下面貼幾張除錯時的圖片:(OS: Win7x64  IDE: VS2010)

繼承關係如圖

1、首先進入派生類建構函式的斷點

2、進入了虛繼承的基類構造的斷點。按照繼承時的順序,CVBase在CBase之後的,但因為是虛繼承所以先執行它的構造

3、執行完CVBase的構造後接著執行CBase的構造

4、最後執行CInner的構造

5、後面將執行CDerive構造中自己寫的程式碼了,但除錯時忘了給這一步截圖,這裡也就沒圖可貼了 0.0~