2013-08-28 10 views
21

私はこのためにGoogleでヒットを見つけるのが大変です。打ち鳴らす3.2でメンバー初期化子は非静的なデータメンバーまたは基本クラスの名前を付けません

struct a { 
    float m_x; 
    float m_z; 
public: 
    a(float x): m_x(x) {} 
}; 

class b : public a { 
    b(float z): m_z(z) {} 
}; 

error: member initializer 'm_z' does not name a non-static data member or base class 
    b(float z): m_z(z) {} 
+0

なぜ:あなたはそれをこのように書くかもしれない前者の場合には

?私はまだ "悪の継承のダイヤモンド"を作っていない。 @ AndreyTその質問の受け入れられた答えは基本的なctorを作ることを言う。私は1つ持っている...ああ。私は、基本クラスctorではなく、メンバーctorを呼び出す必要があると思います。 OK。 –

+0

@WhozCraig:仮想基盤であっても、*間接*メンバーを初期化することはできません。仮想継承では、メンバーではなく、間接*の基底*を初期化する必要があります。 – AnT

+1

@Steven Lu:答えによれば、 'a :: m_z'は' a'のコンストラクタ初期化子リストからのみ初期化できます。 'b'のコンストラクタの初期化子リスト(あなたのコードのように)には記述できません。言語はそれを許さない。それがポイントです。私。 'm_x'に対して行ったように、' m_z'のための 'a'のコンストラクタに別のパラメータを追加し、そのコンストラクタを通して' b'の初期値を渡す必要があります。ところで、上のコードでは、 'b'のコンストラクタから' a'のコンストラクタを参照する必要があります。さもなければ、 'a'にデフォルトコンストラクタがないので、コンパイルされません。 – AnT

答えて

26

はありませんあなたが直接初期化子リストから基本クラスのメンバを初期化することはできません。

:初期進行の順序ので、これは、このように

C++標準n3337 §非委任コンストラクタ、 次の順序で初期化が進行中 12.6.2/10

あります - 最初に、ほとんどの 派生クラス(1.8)のコンストラクタに対してのみ、仮想基本クラスは の順序で初期化されます。これらは、基底cの非循環グラフ の奥行き最初の左から右への走査に現れますここで、「左から右」は、派生クラス ベース指定子リスト内の基本クラスの外観の の順番です。

- 彼らは(かかわらず、MEM-初期化子のオーダーの)ベース指定子リスト に表示されるそして、直接基底クラスは 宣言順にに初期化されます。

- 次に、 非静的データメンバは、彼らが(再びかかわらず MEM-初期化子の順序の) クラス定義で宣言された順にに初期化されます。

- 最後に、 コンストラクタ本体の複合文がで実行されます。

[注:基本および メンバサブオブジェクトが、 初期化の逆の順序で破棄されるようにするには、宣言の順序が必須です。 - エンドノート]

ですから、基本クラスのコンストラクタを指定します(それが保護することができます)と、派生クラスの初期化リスト内の1つの(should be preferred)ことを使用するか、基底クラスのメンバにを割り当てることができますすることができます派生クラスのctorボディ(異なる動作、異なる効果、そして効率の悪さ - デフォルトの初期化(すでに値を持っている)メンバーに割り当てる)。

struct A { 
    float m_x; 
    float m_z; 
    A(){} 
protected: 
    A(float x): m_x(x) {} 
}; 

class B : public A { 
public: 
    B(float z) : A(z) {} 
    // alternatively 
    // B(float z) { 
    //  m_x = z; 
    // } 
}; 

int main(){ 
    B b(1); 
    return 0; 
} 
関連する問題