10

明確にするために、私は多重継承が良いか悪いかを尋ねていません。私はその議論の両側から多くの議論を聞いた。

C ++には、多重継承が何かを達成する唯一の方法であるか、少なくとも他のすべての選択肢よりも最適な方法であり、それが実現しないような設計上の問題やシナリオがあるのではないかと思います。他のことを考える感覚。

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

4

10 に答える 10

11

多重継承なしではポリシーベースの設計はできません。したがって、ポリシーベースの設計が問題を解決するための最も洗練された方法である場合、それは、他のすべてのオプションよりも、問題を解決するために多重継承が必要であることを意味します。

多重継承は、誤用されていなければ (どの言語でもそうですが) 非常に便利です。

于 2009-07-07T18:45:50.543 に答える
5

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

于 2009-07-07T18:46:57.187 に答える
4

C++ ストリームは多重継承を使用します:istreamostreamは両方とも の親ですiostream。どちらも から継承しios_baseているため、ダイヤモンドを持っています。

標準ライブラリのストリーム部分がアルゴリズムやコレクションと同じ方針をとるのは不合理であるという意味で、これは唯一の「合理的な」解決策です。そのため、ostream は、Iterator(*) のような「ダック型」のインターフェイスではなく、ポリモーフィックに動作します。

動的ポリモーフィズムがあるとすぐに、複数のインターフェースを同時に実装するために多重継承が必要になります。

(*) これはおそらく、それ以外は修羅場になるためです。ユーザーにどこでもテンプレートを強制するのではなく、ストリームを操作する実際の関数を記述できる必要があります。これは、「あるストリーム、実行時まで何がわからない」という書き込みは一般的ですが、「あるコレクション、実行時まで何がわからない」という操作はしたくないためです。

于 2009-07-07T19:09:59.230 に答える
3

多重継承は、コントラクトだけでなく動作を継承する必要がある場合に役立ちます。ただし、他の言語が示すように、継承ツリーをより深くすることを犠牲にして、多重継承がその問題を解決する唯一の方法ではありません。そのため、多重継承のみを使用する必要があり、使用する可能性があるシナリオは非常にまれです。

于 2009-07-07T18:56:59.443 に答える
2

この質問に対する答えをよりよく理解するために、Java Interfaces などを読みました。インターフェイスの背後にある考え方は、別のクラスのテンプレートとして機能する抽象クラスを作成することです。ここでの利点は、テンプレートを具象クラス内で組み合わせることができることです。例えば-

親クラス - FoodStore サブクラス - CoffeeShop サブクラス - ベーカリー

この継承ツリーでは、FoodStore を Bakery または CoffeeShop にすることができますが、両方にすることはできません。では、スターバックスを何と呼ぶでしょうか。

いい方法だ、IMO-

親クラス - FoodStore インターフェイス - CoffeeShop インターフェイス - ベーカリー

public class Starbucks extends FoodStore implements CoffeeShop, Bakery { ... }

それを理解するには、Java について少し知っておく必要がありますが、それを試してみてください。インターフェースはかなり初歩的です、IMO。

さらに考えてみると、インターフェイスは「同じことを繰り返すな」に従うように設計されているのかもしれません。明らかに、私がそれについて言及した今。

于 2009-07-07T18:47:13.520 に答える
1

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

于 2009-07-07T19:25:14.350 に答える
0

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

C ++でポリモーフィズムを使用するには、合成を使用できません。(パブリック)継承を使用する必要があります。

したがって、クラスBarがPrintableおよびSerializableから(公に)継承する場合、オブジェクトを印刷可能なオブジェクト、シリアル化可能なオブジェクト、またはBarオブジェクト(ポインターまたは参照を使用)のように扱うことができます。

作曲では、それはできません。

于 2009-07-08T02:51:12.410 に答える
0

Multiple Inheritance の美しい実装を見たい場合は、Eiffel をチェックしてください。機能の名前を変更することでダイヤモンドの問題を解決します。これは、スコープの解決よりもはるかに簡単であり、次のような直接の繰り返し継承もサポートしています。

A は B、B、B を継承します

このタイプの継承を使用する必要が生じた場合。

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

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

于 2009-07-08T03:59:33.583 に答える
0

他の回答で言われているように:

  • Java ( http://en.wikipedia.org/wiki/Interface_(Java) ) のように、純粋な仮想基本クラスを「インターフェース」として使用することは、Java だけでなく、すべての OO 言語で非常に一般的な OO パターンです。

  • 警察系のデザインをする

だけでなく:

  • いくつかの mixin でクラスを構成するには ( http://en.wikipedia.org/wiki/Mixin ); これは、コードの再利用を実現するための多重継承の非常に優れた使用法だと思います。
于 2009-07-07T19:08:40.793 に答える
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::Object から派生する必要があります。2 番目の階層では、ユーザーは実行時にメンバーの名前を照会できるオブジェクトを作成でき、そのようなオブジェクトはすべて Reflectives::Object から派生する必要があります。

両方を実行できるオブジェクトが必要な場合は、次のように記述するだけです。

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

他の解決策は不合理です。

于 2009-07-07T19:57:40.650 に答える