2009-07-07 6 views
10

明確にするには、複数の継承が良いか悪いのかを尋ねるのではありません。私はその議論の両面から多くの議論を聞いた。複数の継承が妥当な解決策になるのはいつですか?

私は、複数の継承が何かを達成する唯一の方法であるか、少なくともそれが他のすべての選択肢よりも最適な方法であるというC++の設計上の問題やシナリオがあるかどうか疑問に思っています他の何かを考慮する意味がないでしょう。

明らかに、この質問は多重継承をサポートしていない言語には当てはまりません。

+0

同様の質問:http://stackoverflow.com/questions/573913/a-use-for-multiple-inheritance –

答えて

10

policy-based design複数の継承を行うことはできません。したがって、ポリシーベースの設計が問題を解決する最もエレガントな方法であれば、他のすべてのオプションよりも問題を解決するために複数の継承が必要になることを意味します。

複数継承は、(すべての言語のように)誤用されていないと非常に便利です。

+2

これはポリシーベースのデザインは、単に言語では不可能であることを暗示するがJavaのような、またはそれを回避する方法はありますか? –

+0

実際、リンクされた記事は、複数の継承が最も重要な実装パターン(いくつかの重要な利点を持つ)であることを示しており、必ずしも必要というわけではありません。 – GalacticCowboy

+0

@Jeff L:Javaの 'Proxy'クラスを回避策として使用できます。 – finnw

5

クラスから継承し、Javaで1つまたは2つのインターフェイスを実装する状況があります。これは、あなたがC++で多重継承で解決するものです。

2

私はJava Interfacesなどを読んで、この質問に対する答えをよりよく知ることができます。インターフェイスの背後にある考え方は、別のクラスのテンプレートとして機能する抽象クラスを作成することです。ここでの利点は、テンプレートを具象クラス内で結合できることです。この継承ツリーでSubclass-コーヒーショップ Subclass-ベーカリー

例 -

親クラス - FoodStore について、FoodStoreはベーカリーやコーヒーショップではなく、両方にすることができます。でも、スターバックスとは何を呼ぶのですか?

良い方法、IMO-

親クラス - FoodStore Interface-コーヒーショップ Interface-ベーカリー

スターバックスがFoodStoreは、コーヒーショップ、ベーカリーを実装して拡張する

パブリッククラス{...}

あなたはよそれを理解するには少しJavaを知っている必要がありますが、それを持っています。インターフェイスはかなり初歩的なIMOです。

さらに気になるように、おそらくインターフェイスは「自分を繰り返さないでください」に従うように設計されています。明らかに、今私はそれを言及する。あなたは行動だけではなく、契約を継承する必要がある場合

3

多重継承は便利です。しかし、他の言語が示すように、継承ツリーを深くする代わりに、複数の継承だけでその問題を解決する方法ではありません。したがって、の場合は、は複数の継承を使用するシナリオは非常にまれです。

0

としては、他の回答に言われています

  • 「インターフェース」として純粋仮想基底クラスを使用して、Javaの(http://en.wikipedia.org/wiki/Interface_(Java))のように、これは非常に一般的であるO.O.全てのO.O.言語、Javaの

    だけでなく
  • は警察ベースの設計

しかし、また、実行します。いくつかのミックスイン(http://en.wikipedia.org/wiki/Mixin)とクラスを構成するには

  • を。私はこれをコードの再利用を達成するために複数の継承を使用するのが非常に良いと考えています!
3

複数の継承を使用するストリーム:istreamおよびostreamは両方ともiostreamの親です。彼らは両方ともios_baseから継承しているので、あなたはダイヤモンドを持っています。

標準ライブラリのストリーム部分がアルゴリズムとコレクションと同じ行をとるのは無理でしょう。したがって、ostreamはIterator(*)のような「ダック型」のインターフェースではなく、多態的に動作します。

動的多形性を取得したらすぐに、複数のインターフェイスを同時に実装するために複数の継承が必要です。

(*)おそらくこれは他の何かが騒ぎになるからです。ストリームを操作する実際の関数を書くことができなければなりません。これは、「一部のストリーム、実行時まではわかりません」に書き込むのが一般的ですが、「一部のコレクションを操作したくない場合は、実行時まで何がわかりませんか」という理由があります。

1

boost::noncopyable(これをサポートする他の言語(JavaおよびC#とは異なります)をmixinと呼ぶ場合は、ロールではなく機能を継承したい場合。

0

2つ以上のサードパーティのクラス階層を結合する必要がある場合、それぞれがオブジェクトを階層の独自のBaseクラスから派生させる必要がある場合、複数の継承がないと、コードが複雑になります。

namespace Object_Database { 
    class Object { 
     public: 
     virtual void store() ; 
     virtual void fetch() ; 
    }; 
} 

namespace Reflectives { 
    class Object { 
     public: 
     virtual std::vector<std::string> > membernames(); 
     virtual std::vector<std::string> > methodnames(); 
    }; 
} 

第一階層は、ユーザーがオブジェクト・データベースへとからシリアライズ、全てのそのようなオブジェクトはクラスObject_Database ::オブジェクトから派生されることを必要とすることができるオブジェクトを作成できます。 2番目の階層では、実行時にメンバの名前を問い合わせることができるオブジェクトを作成し、すべてのオブジェクトをReflectives :: Objectから派生させる必要があります。

あなたが両方を行うことができますオブジェクトが必要な場合は、次のように記述する必要があります。

class ReflectivePickle : 
    public Object_Database::Object, 
    public Reflectives::Object { 
    // ... 
    }; 

他のソリューションは無理です。

0

基本クラスが「インターフェイスクラス」、つまりすべてのメソッドが純粋仮想であり、実装がない基本クラスの場合、C++で多重継承を使用する傾向があります[実装を定義することはできますが、呼び出す必要があります明示的に]、データメンバーはありません。 Javaの「インターフェース」や(私が聞いたことから)C#と非常によく似ています。

多態性をC++で使用するには、合成を使用できません。継承を使用する必要があります。

バーがPrintableおよびSerializableから(publicly)継承されていれば、オブジェクトを印刷可能オブジェクト、直列化可能オブジェクト、またはBarオブジェクト(ポインタまたは参照を使用)のように扱うことができます。

構図では、それはできません。

0

あなたは多重継承の美しい実装を見たい場合は、エッフェル塔をチェックしてください。彼らは、スコープ解決よりもはるかに簡単に、特徴リネームを通じてダイヤモンドの問題を解決し、それも、そのようなことを直接繰り返し継承をサポートします。

継承B、B、B

必要が相続のこのタイプを使用する必要が生じます。

カーネルライブラリはオープンソースであり、例を見たい場合は多重継承が広く使用されています。

http://sourceforge.net/projects/eiffelstudio/files/

関連する問題