仮想基本クラス
クラスが派生クラスに複数回間接基本クラスであるため C++ ではを最適化する方法にこのような基本クラスを提供します。仮想基本クラスはスペースを節約し多重継承するクラスの階層構造のあいまいさを避ける方法を示します。
それぞれの非オブジェクトは基本クラスで定義されたデータ メンバーのコピーが含まれています。この複製を利用するたびにスペースを余分に基本クラスのメンバーをコピーするかを指定する必要があります。
基本クラスが仮想基本クラスとして指定するとデータ メンバーの複製間接基本クラスとしてなしで複数回も機能します。データ メンバーの実体は仮想基本クラスとして使用するすべての基本クラスで共有されます。
仮想基本クラスを宣言すると 仮想 のキーワードは派生クラスの基本クラスのリストに表示されます。
擬似昼食の行を示す次の図のクラス階層構造について考えてみます。
シミュレートされた行昼食グラフ
図ではQueue は CashierQueue と LunchQueue 両方の基本クラスです。ただしLunchCashierQueue を作成するにはクラスの両方で組み合わせると次の問題が発生します : 新しいクラスは CashierQueue の型 Queue1および 2 LunchQueue 他のサブオブジェクトが含まれています。次の図は概念的なメモリ レイアウトを示します (実際のメモリ レイアウトは最適化される場合があります)。
擬似昼食行のオブジェクト
LunchCashierQueue のオブジェクトに Queue 2 のサブオブジェクトがあることに注意してください。次のコードは仮想基本クラスとして Queue を宣言しています :
// deriv_VirtualBaseClasses.cpp
// compile with: /LD
class Queue {};
class CashierQueue : virtual public Queue {};
class LunchQueue : virtual public Queue {};
class LunchCashierQueue : public LunchQueue, public CashierQueue {};
virtual のキーワードはオブジェクト Queue の 1 種類のコピーだけが含まれていることを確認します (次の図を参照)。
仮想基本クラスを使用してシミュレートされた昼食行のオブジェクト
クラスは指定された型の非仮想コンポーネントおよびコンポーネントを使用できます。これを次の図に示す条件で発生します。
同じクラスの仮想 Nonvirtual とコンポーネント
図ではCashierQueue と LunchQueue は仮想基本クラスとして Queue を使用します。ただしTakeoutQueue は基本クラスの仮想基本クラスではなくとして Queue を指定します。したがってLunchTakeoutCashierQueue に型 Queue のサブオブジェクトがあります : 2 LunchCashierQueue とその TakeoutQueue を含むパスから継承のパス 1 から 1 です。これを次の図に示します。
仮想継承のオブジェクトと Nonvirtual のレイアウト
[!メモ]
仮想継承は仮想継承と比較すると重要なサイズの利点があります。ただしオーバーヘッドを処理しているためさらにが発生することがあります。
派生クラスが仮想基本クラスから継承し仮想基本クラスへのポインターを使用して機能する派生クラスでは基本のコンストラクターやデストラクター仮想関数をオーバーライドするとコンパイラが仮想基本クラスを含むクラスに追加非表示になっている 「の」 vtordisp フィールドが生じる場合があります。/vd0 コンパイラ オプションは隠し vtordisp コンストラクター / デストラクター ディスプレイスメント メンバーの追加を抑制します。必要な場合は /vd1 コンパイラ オプションは既定でこれらを有効にします。すべてのクラス コンストラクターとデストラクターが仮想関数呼び出しを有効にしている場合にのみ vtordisps をオフにします。
/vd コンパイラ オプションはモジュールのコンパイルに影響します。クラスの基本クラスごとに対して vtordisp フィールドを抑制し再度有効にするために vtordisp のプラグマの使用 :
#pragma vtordisp( off )
class GetReal : virtual public { ... };
#pragma vtordisp( on )