關於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~