【C++札記】C++構造及析構函數執行順序

前不久,一個朋友面騰訊社招的後臺開發崗,和他聊了聊,他說騰訊的一面仍是比較重基礎的,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()

運行結果能夠看出:類在構造的時候會先從左到右調用父類的構造函數,而後調用類對象成員構造函數,最後調用自身構造函數。析構的順序與構造的順序相反。操作系統

推薦閱讀:

精心整理 | 歷史乾貨文章目錄
【福利】本身蒐集的網上精品課程視頻分享(上)
【數據結構與算法】 通俗易懂講解 二叉樹遍歷
【數據結構與算法】 通俗易懂講解 二叉搜索樹


專一服務器後臺技術棧知識總結分享

歡迎關注交流共同進步

【C++札記】C++構造及析構函數執行順序

碼農有道 coding

碼農有道,爲您提供通俗易懂的技術文章,讓技術變的更簡單!

相關文章
相關標籤/搜索