5

だから私はこの考えを持っています.C ++で実装することは基本的に不可能だと思います...しかし、私は尋ねたい. Stroustrup の第 15 章を読みましたが、答えが得られませんでした。継承ダイヤモンドに関する他の 10 億の質問がこの質問に答えているとは思わないので、ここで質問します。

問題は、共通の基本クラス自体を共有する 2 つの基本クラスから継承するとどうなるかということですが、実質的には 2 つのうちの 1 つだけが継承されます。例えば:

class CommonBase { ... };

class BaseA : CommonBase { ... };

class BaseB : virtual CommonBase { ... };

class Derived : BaseA, BaseB { ... };

私がこれをやりたいと思う理由は、ライブラリ全体を再コンパイルせずに既存のライブラリを拡張しようとしているからです (ワームの缶を開きたくない)。変更したい継承のチェーンが既に存在します。基本的にはこのようなものです(アスキーアートを許してください)

    LibBase
         | \
         |  \ 
         |   MyBase
         |     |
         |     |
 LibDerived    |
         | \   |
         |  \  |
         |   MyDerived
         |     |
LibDerived2    |
         | \   |
         |  \  |
         |   MyDerived2
         |     |
LibDerived3    |
         | \   |
         |  \  |
         |   MyDerived3
         |     |
LibConcrete    |
           \   |
            MyConcrete

写真をゲット?各Myクラスのオブジェクトを、それら本質的に置き換えるクラスのオブジェクトにしたいのですが、継承図の次のクラスでは、My基本クラスからオーバーライドされたメソッド実装を使用する必要がありますが、他のすべてのメソッドはライブラリのクラス。ライブラリのクラスは事実上継承しないのでこんな感じ

class LibDerived : LibBase

しかし、クラスを事実上継承させると

class MyBase : virtual LibBase {};
class MyDerived: virtual MyBase, virtual LibDerived {};

MyDerivedvtableがあり、vtableがあるため、オブジェクトMyBaseは1つだけですか?LibBase

この質問が十分に明確であることを願っています。

4

2 に答える 2

2

答えを単純化するために、仮想/非仮想を複製または非複製のコンテンツとして考えてみましょう。

class LibDerived : LibBase

宣言:LibBaseをLibDerivedの降順に2回(またはそれ以上)入力することを許可します

class MyBase : virtual LibBase {};

宣言:コンパイラがMyBaseの子孫にあるLibBaseの2つのエントリを1つに最適化できるようにします。

これらの2つの宣言がそれぞれに一致する場合、最初の宣言がより優先されるため、MyDerivedはLibBaseの2つの実装を取得します。しかし、C ++の力はそれを解決する可能性です!MyDerived仮想関数をオーバーライドして、使用する仮想関数を選択するだけです。別の方法-任意のインスタンス(LibDerived、MyBase、...)を集約するインターフェイスLibBaseから派生したMyDerivedのユニバーサルラッパーを作成し、集約から期待されるメソッドを呼び出します。

于 2009-08-07T15:52:12.347 に答える
2

本質的に、あなたは正しいです。この種の継承ツリーを機能させたい場合は、LibDerived仮想的に派生する必要があります。LibBase

LibBaseこれがないと、 の下に非仮想があり、 の下に別LibDerivedの仮想があることを防ぐことはできません。LibBaseMyBase

于 2009-08-07T15:41:12.167 に答える