2016-05-07 74 views
2

我有這樣的C++代碼順序:解釋該類別中的構造函數/析構函數調用++代碼

class BaseClass { 
    int id; 
public: 
    BaseClass() { printf("BaseClass()\n"); } 
    virtual ~BaseClass() { printf("~BaseClass()\n"); } 
}; 

class Class1 : public BaseClass 
{ 
    int id; 
public: 
    Class1() { printf("Class1()\n"); } 
    ~Class1() { printf("~Class1()\n"); } 
}; 

class Class2 : public Class1 
{ 
    BaseClass id; 
public: 
    Class2() { printf("Class2()\n"); } 
    ~Class2() { printf("~Class2()\n"); } 
}; 

class Class3 : virtual public BaseClass 
{ 
    int id; 
public: 
    Class3() { printf("Class3()\n"); } 
    ~Class3() { printf("~Class3()\n"); } 
}; 

class Class4 : public Class3, virtual public Class1 
{ 
    Class3 id; 
public: 
    Class4() { printf("Class4()\n"); } 
    ~Class4() { printf("~Class4()\n"); } 
}; 

int main(int argc, char* argv[]) 
{ 
    BaseClass *p = new Class2; 
    Class2 *p1 = new Class2; 
    Class3 *p2 = new Class3; 
    delete p; 
    delete p1; 
    delete p2; 
    return 0; 
} 

這是輸出:

BaseClass() 
Class1() 
BaseClass() 
Class2() 
BaseClass() 
Class1() 
BaseClass() 
Class2() 
BaseClass() 
Class3() 
~Class2() 
~BaseClass() 
~Class1() 
~BaseClass() 
~Class2() 
~BaseClass() 
~Class1() 
~BaseClass() 
~Class3() 
~BaseClass() 

,我不明白爲什麼。我期望的輸出如下:

BaseClass() 
Class1() 
Class2() 
BaseClass() 
Class1() 
Class2() 
... 

Class1()後創建的時候,例如爲什麼不Class2()印刷,p1? 這是否與虛擬繼承有關?

+0

當一個類A繼承類B,B類的建設需要A級將首先構建 - 爲B的建設可能需要使用 –

+0

@songyuanyao我無意中冷落複製輸出時的第一行,抱歉。 – Eutherpy

回答

2

我們正在建設的一步步走與第一對象:

new Class2; 

這是你contructing的第一個對象,讓我們把它叫做p

BaseClass() 

pBaseClass

Class1() 

pClass1,的BaseClass子類被構造。

BaseClass() 

這是被構造的Class2id構件。

Class2() 

而現在,終於,Class2p本身。

因此,儘管您有其他看法,Class2()Class1()後面打印。除了你忘了Class2也有一個id成員,那是一個BaseClass,並且還必須在構造函數Class2::Class2()被調用之前構造它。您認爲您正在構建第二個new編輯對象的BaseClass,但實際構建的是BaseClass成員對象。

P.S.這是C++。在C++我們使用std::cout而不是printf()。 printf()是如此...上個世紀。

+0

當然......我完全忽略了這一點,甚至沒有注意到'id'不是像'BaseClass'和'Class1'中的整數。這樣一個蹩腳的錯誤:)順便說一下,這不是我的代碼。 :) – Eutherpy

3

爲什麼在創建Class1()時不打印Class2(),例如p1?

因爲Class2具有BaseClass型非靜態成員對象,它的構造函數將被的Class2的構造函數之前調用。

按照initialization order

初始化順序

1)如果構造爲最派生類,虛基 類的順序初始化的在它們出現在 深度 - 基類聲明的第一次從左到右的遍歷 (從左到右指的是基指定符列表中的外觀)

2)然後,直接基類是i nitialized在左到右的順序 他們出現在這個類的基本說明符列表

3)然後,非靜態數據成員在類定義 聲明的順序初始化。

4)最後,構造體被執行

對於new Class2;,直接基類Class1和它的基類BaseClass將被首先調用。然後調用類型爲BaseClass的非靜態數據成員id。最後調用Class2的ctor體。所以,你會得到

BaseClass() 
Class1() 
BaseClass() 
Class2() 
相關問題