3

コンテキスト 1: クラス D: public B1、public B2{};

コンテキスト 2: B2 は B1 を使用して初期化します: B2( B1 * ) //B2 のコンストラクター

私の質問はDの初期化リストにあります:

D::D() : B1(), B2( ? )... には何が必要ですか?

? に " (B1*)this " を入れたくない 初期化リストで「this」を使用するのは良くないためです。そして B1 部分は初期化されているので、それを使用するのは理にかなっています。

私は何をすべきか ?

4

2 に答える 2

3

B1の部分thisは既に初期化されているので使用しても大丈夫です。§12.6.2/5:「直接基本クラスは、(mem-initializersの順序に関係なく)base-specifier-listに表示される宣言順序で初期化されるものとします。」

ここでのbase-specifier-listはですclass D : public B1, public B2。mem-initializer-listはD::D() : B1(), B2( … )です。

でも、これには「コードの臭い」があると思います。

編集:thisメンバーの初期化子が含まれていないコンストラクターの本体の外部で未定義であるかどうかについて、あなたの懸念を理解しました。これを可能にする言葉は2つの例の間に埋もれていて、最初はそれを見逃しました。パラグラフ7:「mem-initializerの式リスト内の名前は、mem-initializerが指定されているコンストラクターのスコープで評価されます。」

B2実際にへのポインタを保持する必要がB1あり、そのポインタが常に最も派生したオブジェクト内を指す場合は、仮想継承を検討してください。

class B1 {};
class B2 : virtual B1 {}; // under the hood, B2 has a pointer to B1.
class D : public virtual B1, public B2 {}; // D has a pointer too
 // Only the most-derived class (the one actually used for instantiation)
 // implements space for and initialization of the B1.
于 2010-04-12T05:21:44.067 に答える
1

これは危険なコードです。前に指摘したように、B1 は B2 の前に構築されるため、安全にこれを行うことができますが、クラス定義が変更された場合はそうではなくなり、コード内の無関係な場所にあるため、あなたがそれを壊すとき、あなたが壊しているコード。

このデザインを詳しく見てみたいのですが、これを不要にするために変更することは可能ですか? 継承するのではなく、カプセル化するメンバーに物事を移動できますか? D は本当に B1 と B2 ですか?

于 2010-04-12T05:51:17.357 に答える