2
AFAIK、仮想継承はダイヤモンドの問題を解決しますが、単純に仮想を使って基本クラスから継承するとどうなりますか?ここでvirtual
を使用する場合の違いは何ですか?基底クラスからの仮想継承
class A
{
/* ... */
};
class B : virtual public A
{
/* ... */
};
AFAIK、仮想継承はダイヤモンドの問題を解決しますが、単純に仮想を使って基本クラスから継承するとどうなりますか?ここでvirtual
を使用する場合の違いは何ですか?基底クラスからの仮想継承
class A
{
/* ... */
};
class B : virtual public A
{
/* ... */
};
いくつかの違いがあります。オブジェクトのレイアウトは異なります(仮想継承の場合は、派生サブオブジェクトのベースへの追加の隠れポインタがあります)。サブオブジェクトの初期化は異なります(B
から派生するタイプはA
コンストラクタを直接呼び出す必要があります)。初期化リスト)。 B
のメンバ関数では、A
メンバ(データまたは関数)を参照するコードは、(前述したポインタを介して)余分な間接化やその他の相違が必要になります。
仮想継承は複雑な問題であり、あなたの前の質問に対する回答に含まれるリンクの多くを読んで、別々の質問からちょっとしたものを得るだけで、理解するようにしてください。
ヒント:仮想継承がコンパイラによってどのように処理されるかの詳細を理解するには、オブジェクトのメモリレイアウトに焦点を当てる必要があります。なぜ仮想的に派生するクラスごとに余分なポインタが必要なのか理解したら、残りの部分は単純です。