2011-09-10 29 views
4

基本クラスの仮想継承が、複数の派生クラス間で共通の共有基本クラスを作成し、DDD問題に対処することを理解します。ベースクラスに派生クラスが1つしかない場合、ベースを仮想的または非仮想的に継承すると違いがありますか?基本的には、クエリIs it possible to forbid deriving from a class at compile time?で説明されている説明を理解しようとしています。Usage_lock基本クラスは、Usableというクラスの派生を防ぐために事実上継承されています。この仮想キーを削除すると、動作が変わります。つまり、Usableからサブクラスを派生させることができます。ですから、私は単一の継承シナリオで仮想キーの違いを理解したいと思います。単一の仮想継承

答えて

2

仮想基本クラスは、最も派生したクラスによって構築されます。事実上派生し、そのような基底のコンストラクタを非公開にすることによって、別のクラスがそれを構築する方法がないため、派生を効果的に防ぐことができます。しかし、それは非常に人工的な構造物であり、それにはあまりにもオーバーヘッドがあります。

5

単一の仮想継承の主な違いは、最も派生したクラスだけが仮想的に継承された基底のコンストラクタを呼び出し、他のすべてのクラスは構築されたクラスへの参照が提供されることです(これは裏側で起こります) 。

そうで、この例では、さらにUsableを導出しようとするので、(プライベートで)Usable_lockコンストラクタを呼び出すために新しいクラスを必要とする、それがUsable由来する任意の他のクラスのために不可能です。ロック対象の友人であるため、Usableのみがロックオブジェクトを構築できます。

+0

おかげで、私は基本コンストラクタにブレークポイントを設定することで、それを見ることができます。ありがとうございました。 – irappa

2

仮想継承は基本的にDiamond shaped Inheritanceの古典的な問題を解決するために導入されました。

は、次のクラスを考えてみましょう。ここ

class Base {}; 

class Derived1: Base {}; 
class Derived2: Base {}; 

struct MostDerived: Derived1, Derived2 {}; 

MostDerivedクラスがあるため、この菱形の階層のBaseの2のインスタンスを持っています。

この問題を解決するために、C++はvirtualキーワードを使用し、仮想継承という概念を導入しています。
したがってとして、ここではvirtualキーワードを追加:

class Derived1: virtual Base {}; 
class Derived2: virtual Base {}; 

は今だけBaseMostDerived内部クラスのインスタンスが1つになることを保証します。
MostDerivedクラスは、このコンストラクタを呼び出すことによってBaseクラスのインスタンスをインスタンス化します。上記背景と

(太字のテキストを強調)、コード例については、以下の点を考慮してください。派生クラスUsableMUSTオブジェクトのUsable_lock基本クラスをインスタンス化するよう

Usableクラスは、Usable_lockから実質的に導出しますそのコンストラクタを呼び出すことによって。

しかし、Usable_lockクラスにはプライベートコンストラクタがあり、クラス自体がコンストラクタにアクセスできるため、他のクラスがそれから派生するのを防ぐことができます。C++ 03標準から


リファレンス:
セクション12.6.2初期化塩基およびメンバー
パラグラフ6:仮想基本クラスを表す

すべてのサブオブジェクトであります最も派生したクラス(1.8)のコンストラクタによって初期化されます。最も派生したクラスのコンストラクタが仮想基本クラスVのmem初期化子を指定していない場合、Vのデフォルトコンストラクタが呼び出され、仮想基本クラスのサブオブジェクトが初期化されます。 Vにアクセス可能なデフォルトのコンストラクタがない場合、初期化は正しく行われません。仮想基本クラスの名前を付けるmem初期化子は、最も派生したクラスではないクラスのコンストラクタの実行中は無視される。

+0

これをdownvotingする*本当の*理由は? –