6

コードスニペットから始めましょう:

#include <iostream>

struct God{
    God(){_test = 8;}
    virtual ~God(){}
    int _test;
};

struct Base1 : public virtual God{
    //Base1(){std::cout << "Base1::Base1" << std::endl;}  //enable this line to fix problem
    virtual ~Base1(){}
};

struct Base2 : public virtual Base1{
    virtual ~Base2(){}
};

struct A1 : public virtual Base2{
    A1(){std::cout << "A1:A1()" << std::endl;}
    virtual ~A1(){};
};

struct A2 : public virtual Base2{
    A2(){std::cout << "A2:A2()" << std::endl;}
    virtual ~A2(){};
};


struct Derived: public virtual A1, public virtual A2{
    Derived():Base1(){std::cout << "Derived::Derived()" << std::endl;}
    Derived(int i){std::cout << "Derived(i)::Derived(i)" << std::endl;}         
    virtual ~Derived(){}
};


int main(){

    God* b1 = new Derived();
    std::cout << b1->_test << std::endl;    //why it prints 0?

    God* b2 = new Derived(5);
    std::cout << b2->_test << std::endl;

    return 0;
}

GCC 4.5.1 および 4.6.1 でコンパイルされた Derived クラスのコンストラクター間の唯一の違いは、最初のコンストラクターが、どの Base1 コンストラクターを呼び出す必要があるかを明示的に示していることです。main() の両方の cout が 8 を出力することを期待します。残念ながら、最初のものは 0! を出力します。

なんで?

Base1 コンストラクターの明示的な定義を有効にすると、問題が修正されます。Derived クラス定義 (クラス Derived: public A1、public A2) で仮想継承を削除すると、同様に機能します。期待される動作ですか?

この問題は、GCC 3.4.4 または Microsoft コンパイラ (VS) では観察できません。

4

2 に答える 2

1

私はいくつかの古いフレーバー(最大4.3-動作します)でテストしました-4.4シリーズは手元にありません(午前中にテストされます)が、これはバグのようです(データベースにはありません)、おそらくそれを上げる価値があります。

Base1ただし、最初の関係を(仮想からGod非仮想に)変更すると、例は期待どおりに機能することに気付きました。Godこれは、最も派生したクラスのctorを直接呼び出すかどうかなど、ニーズによって異なると思います(ただし、このアプローチはこれまで見たことがありません...)

于 2012-02-09T00:01:58.617 に答える
1

これはコンパイラのバグに違いありません。GCC 4.2.1 もテストしましたが、結果はどちらも 8 です。

于 2012-02-08T23:56:05.793 に答える