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()
...

たとえば、作成時にClass2()afterが出力されないのはなぜですか? これは仮想継承と関係がありますか?Class1()p1

4

2 に答える 2

3

たとえば、p1 を作成するときに Class1() の後に Class2() が出力されないのはなぜですか?

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

初期化順序に従って:

初期化順序

1) コンストラクターが最も派生したクラス用である場合、仮想基底クラスは、基底クラス宣言の深さ優先の左から右への走査で出現する順序で初期化されます (左から右は外観を参照します)塩基指定子リスト内)

2) 次に、このクラスの base-specifier リストに表示されるように、直接基底クラスが左から右の順序で初期化されます。

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

4) 最後に、コンストラクターの本体が実行されます

の場合new Class2;、直接基底クラスClass1とその基底クラスBaseClassが最初に呼び出されます。id次に、型を持つ非静的データ メンバーBaseClassが呼び出されます。そして最後に、ctor の本体Class2が呼び出されます。だからあなたは得るでしょう

BaseClass()
Class1()
BaseClass()
Class2()
于 2016-05-07T13:57:51.730 に答える
2

最初のオブジェクトを構築する段階を追ってみましょう:

new Class2;

これはあなたが構築している最初のオブジェクトです。それを と呼びましょうp

BaseClass()

pBaseClass

Class1()

pClass1サブクラスBaseClassが構築されます。

BaseClass()

これは構築中のidメンバーですClass2

Class2()

そして今、最後に、Class2pそれ自体。

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

PSこれはC++です。( )の代わりにC++使用します。そうです...前世紀。std::coutprintfprintf()

于 2016-05-07T13:50:56.207 に答える