2016-05-07 18 views
2

でコンストラクタ/デストラクタ呼び出しの順序を説明する:は、私はこのC++のコードを持って、このC++コード

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

と私は理由を理解していない:

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() 
Class2() 
BaseClass() 
Class1() 
Class2() 
... 

など

例えば、作成するときに Class2()Class1()後に印刷されていないのはなぜ

p1:私は、出力は次の通りであることを期待しますか? これは仮想継承と関係がありますか?

+0

を取得しますので、クラスBの構成は、第1に構築されるクラスAを必要とする - Bの建設は、私が誤って左 –

+0

@songyuanyaoの使用を必要とするかもしれないとして、出力をコピーするときの最初の行、それについて残念。 – Eutherpy

答えて

2

さんが構築されている最初のオブジェクトで段階的に行ってみよう:

new Class2; 

これは、あなたがcontructingしている第一の目的である、のはpそれを呼ばれてみましょう。

BaseClass() 

pさんBaseClass

Class1() 

pさんClass1BaseClassのサブクラスを構築します。

BaseClass() 

これが構築さClass2idメンバーです。

Class2() 

そして今、最終的には、Class2pそのもの。

あなたの信念にもかかわらず、の後にClass2()が印刷されます。 Class2にはidのメンバーもあり、それはBaseClassであり、Class2::Class2()コンストラクターが呼び出される前に作成する必要があることを忘れた点を除いて、あなたは、2番目のnew edオブジェクトのBaseClassが構築されているのを見ていると信じていましたが、本当に構築されたのはBaseClassというメンバオブジェクトでした。

P.S.これはC++です。 C++ではprintf()の代わりにstd::coutを使用しています。 printf()はそう...最後の世紀です。

+0

もちろん...私はこれを完全に無視しましたが、 'id'は' BaseClass'や 'Class1'のような整数ではないことに気がつきませんでした。そのような間違いの間違い:)しかし、それは私のコードではありません。 :) – Eutherpy

3

p1などを作成するときにClass1()の後にClass2()が印刷されないのはなぜですか?

Class2はタイプBaseClassと非静的メンバオブジェクトを持っているので、そのctorのはClass2のctorの前に呼び出されます。

initialization orderによると:コンストラクタは、彼らが 深さに表示されている クラスは順番に初期化されているほとんどの派生クラス、仮想ベースのものである場合

初期化順序

1)基本クラス宣言の左から右へのトラバーサル (左から右は基本指定子リストの出現を参照します)

2)次に、直接基底クラスはi左から右へ順に としてニート化されます。

3)次に、非静的データメンバーは、クラス定義の 宣言の順番で初期化されます。

4)最後に、コンストラクタの本体はnew Class2;について

実行され、直接ベースクラスClass1とその基底クラスBaseClassは、まず呼び出されます。すると、タイプがBaseClassの非静的データメンバーidが呼び出されます。そして最後にClass2のctorの本体が呼び出されます。クラスAがクラスBを継承するときは、

BaseClass() 
Class1() 
BaseClass() 
Class2() 
関連する問題