1

したがって、ダイヤモンド継承の問題があり、仮想継承を行うと、基本クラスの1つだけが作成されることを理解していますが、これはどのように正確に表現されていますか?

vtableには基本クラスへのポインタがあり、派生クラスの1つが構築されると、そのポインタがすでに存在するかどうかを確認し、存在しない場合はそれを作成して基本クラスを指すようにしますか?

4

1 に答える 1

1

あなたは正しく始めます。実装の詳細は異なる場合がありますが、実際には、基本クラスを見つけるのに十分な情報が vtable (またはクラス メタデータ) にあります。

2番目の部分については、どの実装にも「ポインターが既に存在するかどうかを確認する」ことはありません。C++ では、最も派生したクラスがすべての仮想ベースの構築を担当します。Rootしたがって、 、Middle1Middle2およびを含む通常のダイヤモンド継承では、 willMostDerivedのインスタンスを構築するために発行されるコードは次のようになります。MostDerived

  • vptr を構築Rootして設定し、vtable を指すようにします。MostDerived
  • 構築Middle1し、Middle2
  • のデータメンバーを構築するMostDerived
  • のコンストラクタ本体を実行するMostDerived

「vptr」ではなく「vptr」と言います。これはMiddle1Root基本クラスの構築中に利用可能ですが、 の仮想関数は で定義されたオーバーライドをまだ参照してMiddle1 いないMostDerivedためです。Middle1これを整理するのは実装次第です。オブジェクトのサイズを調べて、それを行うために使用される隠しポインターの数と、その数が仮想関数があるかどうかに依存するかどうかを自分で試すことができます。

のインスタンスを構築するために発行される通常のコードは次のようにMiddle1なることに注意してください。

  • vptr を構築Rootして設定し、vtable を指すようにします。Middle1
  • のデータメンバーを構築するMiddle1
  • のコンストラクタ本体を実行しMiddle1ます。

Middle1の基底クラスのサブオブジェクトを構築するときはMostDerived、これらの手順のうち 3 つすべてではなく 2 つだけを実行する必要があります。このため、複数のコンストラクターを持つクラスの発行されたコードには、複数のコンストラクターが含まれていることがわかるでしょう。1 つは、最も派生した型がクラスであるオブジェクト用であり、別のコンストラクターは、型がクラスである基本クラスのサブオブジェクト用です。 .

于 2013-06-07T23:10:10.030 に答える