前不久,一個朋友面騰訊社招的後臺開發崗,和他聊了聊,他說騰訊的一面仍是比較重基礎的,C++,操做系統,網絡、算法這塊問的比較多,即使是社招。其中就有一個C++牽涉到虛擬繼承時其構造和析構順序的題目,這個平時也不太注意,所以也真難住了很多面試者,我那位朋友就是其一,所以有必要總結下。ios
在C++中,當建立一個類對象時,編譯器是會自動調用一個叫構造函數的東西的,咱們知道,C++類與類之間不少狀況下是有關聯的,好比繼承,組合等等,讀懂UML類圖(請戳我)一文中有描述該主題。本文主要經過實例總結各類狀況下的構造與析構順序。面試
繼承
場景:B類繼承兩個父類A和C,每一個類的構造函數和析構函數很簡單,就是打印對應的函數名,以便觀察構造及析構函數執行順序。算法
#include <iostream> using namespace std; class A { public: A(){cout << "A()" << endl;} ~A(){cout << "~A()" << endl;} }; class C { public: C(){cout << "C()" << endl;} ~C(){cout << "~C()" << endl;} }; class B: public A, public C { public: B(){cout << "B()" << endl;} ~B(){cout << "~B()" << endl;} }; int main(int argc, char const *argv[]) { B b; return 0; }
bogon:dataStructure lizhong$ ./t A() C() B() ~B() ~C() ~A()
經過運行結果能夠看出:創造一個子類對象時,先執行父類的構造函數,再執行自身的構造函數,若是子類繼承多個父類,則按照繼承的順序從左到右調用父類構造函數(本例先構造A,再構造C),析構的順序與構造的順序相反。服務器
咱們還知道還有一種繼承叫作虛擬繼承,看看這種狀況下的構造與析構又是怎樣的順序。網絡
#include <iostream> using namespace std; class A { public: A(){cout << "A()" << endl;} ~A(){cout << "~A()" << endl;} }; class C { public: C(){cout << "C()" << endl;} ~C(){cout << "~C()" << endl;} }; class B: public A, public C { public: B(){cout << "B()" << endl;} ~B(){cout << "~B()" << endl;} }; int main(int argc, char const *argv[]) { B b; return 0; }
bogon:dataStructure lizhong$ ./t C() A() B() ~B() ~A() ~C()
能夠看出:虛擬繼承和通常的繼承構造和析構的順序仍是有點不同,父類的構造順序發生了改變,虛擬繼承的C構造函數先被執行,而後是A。最後是自身的構造函數被調用,析構的順序與構造的順序相反。數據結構
成員包含其它類對象成員
場景:B類含有A類對象和C類對象的成員,且在B類中,其成員聲明順序是先聲明c,再聲明a。看看創造B類對象時,構造函數和析構函數的執行順序是怎樣的。ide
#include <iostream> using namespace std; class A { public: A(){cout << "A()" << endl;} ~A(){cout << "~A()" << endl;} }; class C { public: C(){cout << "C()" << endl;} ~C(){cout << "~C()" << endl;} }; class B { public: B():a(A()), c(C()) {cout << "B()" << endl;} ~B(){cout << "~B()" << endl;} C c; A a; }; int main(int argc, char const *argv[]) { B b; return 0; }
bogon:dataStructure lizhong$ ./t C() A() B() ~B() ~A() ~C()
運行結果能夠看出:創造一個B類對象b時,先執行其成員對象所屬類的構造函數,再執行自身的構造函數,若是有多個類對象成員,則按照聲明的順序調用對應類的構造函數(本例先構造C類對象c,再構造A類對象a),析構的順序與構造的順序相反。函數
即有繼承又包含類對象成員
場景:B類繼承兩個父類A和C,而且B類有一個X類的對象成員,觀察構造及析構函數執行順序。spa
#include <iostream> using namespace std; class A { public: A(){cout << "A()" << endl;} ~A(){cout << "~A()" << endl;} }; class C { public: C(){cout << "C()" << endl;} ~C(){cout << "~C()" << endl;} }; class X { public: X(){cout << "X()" << endl;} ~X(){cout << "~X()" << endl;} }; class B: public A, public C { public: B(){cout << "B()" << endl;} ~B(){cout << "~B()" << endl;} X x; }; int main(int argc, char const *argv[]) { B b; return 0; }
bogon:dataStructure lizhong$ ./t A() C() X() B() ~B() ~X() ~C() ~A()
運行結果能夠看出:類在構造的時候會先從左到右調用父類的構造函數,而後調用類對象成員構造函數,最後調用自身構造函數。析構的順序與構造的順序相反。操作系統
推薦閱讀:
精心整理 | 歷史乾貨文章目錄
【福利】本身蒐集的網上精品課程視頻分享(上)
【數據結構與算法】 通俗易懂講解 二叉樹遍歷
【數據結構與算法】 通俗易懂講解 二叉搜索樹
專一服務器後臺技術棧知識總結分享
歡迎關注交流共同進步
碼農有道 coding
碼農有道,爲您提供通俗易懂的技術文章,讓技術變的更簡單!