仮想基底クラスにデータ メンバーを持たないことが推奨されるのはなぜですか?
関数メンバーはどうですか?すべての派生クラスに共通のタスクがある場合、仮想基本クラスがタスクを実行しても問題ありませんか、それともタスクを実行する仮想インターフェイスとプレーン ベースの 2 つのクラスから派生したものを継承する必要がありますか?
ありがとう。
仮想基底クラスにデータ メンバーを持たないことが推奨されるのはなぜですか?
関数メンバーはどうですか?すべての派生クラスに共通のタスクがある場合、仮想基本クラスがタスクを実行しても問題ありませんか、それともタスクを実行する仮想インターフェイスとプレーン ベースの 2 つのクラスから派生したものを継承する必要がありますか?
ありがとう。
仮想継承は通常多重継承で使用され、クラスの 1 つのバージョンのみが派生クラスに存在することを保証するため、慣例として、仮想継承のみを使用してインターフェイスを定義する必要があります。また、純粋なインターフェイスは多重継承の最も安全な形式です。もちろん、自分が何をしているのか分かっていれば、多重継承を好きなように使うことができますが、注意しないと脆弱なコードになる可能性があります。
仮想継承の最大の欠点は、コンストラクターがパラメーターを受け取る場合です。仮想基本クラスのコンストラクターにパラメーターを渡す必要がある場合は、すべての派生クラスにコンストラクターを明示的に呼び出すように強制します (コンストラクターを呼び出す基本クラスに依存することはできません)。
あなたの明示的なアドバイスについて私が見ることができる唯一の理由は、仮想基本クラスのデータにコンストラクターパラメーターが必要になる可能性があることです。
編集 マーティンのコメントの後、いくつかの宿題をしました。マリンに感謝します。最初の行は完全には正しくありません:
仮想継承は通常多重継承で使用され、クラスの 1 つのバージョンのみが派生クラスに存在することを保証するため、慣例として、仮想継承のみを使用してインターフェイスを定義する必要があります。
基本クラスが純粋なインターフェイスである場合、仮想継承に違いはありません (すべてのメソッドが実装されていない場合、vc8 でわずかに異なるコンパイラ エラーが発生する場合を除きます)。基本クラスにデータがある場合にのみ、実際の違いが生じます。この場合、U 字型ではなくひし形になります。
Non virtual virtual
A A A
| | / \
B C B C
\ / \ /
D D
仮想ケースでは、B と C が A の同じコピーを共有しています。
ただし、仮想継承が必要ない場合でも、純粋なインターフェイスが多重継承の最も安全な形式であることについては、他のすべてに同意します。そして、コンストラクターのパラメーターと仮想継承が苦痛であるという事実。
この推奨事項は見たことがありません。
クラスは、密接に関連する関数とデータのセットです。基本クラスの目的は、派生クラスで再利用できる関数とデータの共通セットを持つことです。
基本クラスにデータ メンバーや非純粋仮想関数を持たないように制限すると、コードの再利用の量が減り、長期的にはコードの信頼性が低下することにつながると思います。
C++ でインターフェイスをシミュレートするために使用されるすべて抽象の基本クラスは、データ メンバーを持つべきではありません。これは、インターフェイスを記述しており、インスタンスの状態が実装の詳細であるためです。
それ以外に、仮想関数を含む基本クラスには、データ メンバーが含まれる場合があります。ただし、通常のルールが適用されます。
a) メンバーはプライベートにする必要があります - そのため、派生クラスでそれらを使用すると問題が発生する可能性があります (そのため、ゲッター メソッドとセッター メソッドを追加する必要があり、インターフェイスが破壊されます)
b)現在使用していないものを宣言しないでください-変数にアクセス/使用するクラスでのみ変数を宣言します
c) 仮想基本クラスには、インターフェイス/仮想メソッドのみを含める必要があります。
私の理由が完璧で完全ではなくても、それが少し役立つことを願っています:)
チャオ、クリス