2011-01-31 15 views
3

可能性の重複:私は複数を使用している場合、コンパイラは異なる初期値を処理する方法を疑問を抱いていますこんにちはすべて
gcc c++ virtual inheritance problem仮想基底クラスと初期化リスト

仮想基本クラスからの継承。私は(例えばhere参照)D1D2のための仮想継承を使用し、JoinBaseの2つのコピーを避けるために

 Base 
    /\ 
    / \ 
    D1  D2 
    \ /
    \/
    Join 

:悪名高い「恐怖のダイヤモンド」継承スキームを考えてみましょう。

class Base { 
public: 
    Base(int x_) {x = x_;}; 
    virtual ~Base(){}; 

public: 
    int x; 
}; 

class D1 : public virtual Base { 
public: 
    D1() : Base(1) {}; 
    virtual ~D1(){}; 
}; 

class D2 : public virtual Base { 
public: 
    D2() : Base(2) {}; 
    virtual ~D2(){}; 
}; 

class Join : public D1, public D2 { 
public: 
    Join(){}; 
    ~Join(){}; 
}; 

int main() 
{ 
    Join j; 
    cout << j.x << endl; 

    return 0; 
} 

出力は1、2であるか、またはそれは、コンパイラに依存する:?今、Baseが抽象的ではなく、そのコンストラクタで初期化されたメンバーフィールドを持って言うことができますか

+1

新しいものは必要ありませんが、テストケースコードは 'Join j; cout << j.x; '。 –

+0

@Charles、この質問はGCC固有ではないので、厳密には重複していません。同じ問題に対処していますが、答えはコンパイラに依存しません。 –

+0

@ SergeyTachenov:gccに固有の質問でもありません。ちょっと誤解を招くタイトルにgccがあるだけです。 –

答えて

5

コンパイルしません。仮想基底は、最も派生したクラスJoinによって初期化されます。 Joinは明示的にBaseを初期化しませんが、Baseにはアクセス可能なデフォルトコンストラクタはありません。

[クラスの定義は;で終了する必要があるためコンパイラーではありませんが、これは誤植であると想定しています。 mainintを返す必要がありますし、私はj.xj->xための誤植であると仮定しました。]

+0

修正しました。 – bavaza

2

あなたは仮想継承を持っているとき、それは仮想基底クラスを初期化する必要があり、最終的なクラスです。

ので参加のコンストラクタは、ベースを構築する必要があります。

class Join : public D1, public D2 
    { 
    public: 
     Join() : Base(3){} // or whatever value 
     ~Join(){} 
    }; 

それはクラスのみ正常に彼らの直接のベース・クラスを初期化する規則の例外です。

(それ以外の点mainからintを返す必要がありますし、あなたがjは、ポインタだけでなく、事実であるとして、あなたはnewと呼ばれるよう、あなたがそれをdeleteしなければなりませんj->xないj.xを行う必要があります)

+0

あなたは17秒でそれに私を打つ:D – Palmik

1

ベースはしていませんので、暗黙のコンストラクタを持っているとC1C2の両方が仮想塩基である、あなたはこのようにそれを変更する(ともチャールズ・ベイリーによって指摘されているように、クラスの宣言の残りの部分の後にセミコロンを追加)する必要があります

class Join : public D1, public D2 { 
public: 
    Join() : Base(3) {}; 
    ~Join(){}; 
}; 

int main() 
{ 
    Join j; 
    cout << j.x << endl; 
} 

3を標準出力に出力します

関連する問題