c++ - なぜ私はC ++で多重継承を避けるべきですか?


7 Answers

Bjarne Stroustrupとインタビューから:

複数の継承を使用して行うことができることは、単一の継承を使用して行うこともできるため、複数の継承を必要としないということは、きわめて正しく言います。 あなたは私が言及した委任のトリックを使用するだけです。 さらに、継承を一切必要としません。単一の継承で行うことは、クラスを介して継承することもできます。 実際には、ポインタとデータ構造ですべてを行うことができるので、クラスも必要ありません。 しかし、なぜあなたはそれをしたいですか? 語学施設を利用するのはいつ便利ですか? あなたはいつ回避策を好むでしょうか? 私は複数の継承が有用な場合を見てきましたが、複雑な多重継承が有用な場合も見てきました。 一般的に、私は、その言語で提供されている機能を使用して回避策をとることを好みます

Question

複数の継承を使用するのは良い考えですか?代わりに他のことをすることはできますか?




w: 多重継承を参照してください。

複数の継承は批判を受けており、そのため、多くの言語で実装されていません。 批判には以下が含まれる:

  • 増加した複雑さ
  • 意味論的あいまいさはしばしばダイヤモンドの問題として要約される。
  • 1つのクラスから複数回明示的に継承できない
  • クラスのセマンティクスを変更する継承の順序。

C ++ / Javaスタイルのコンストラクタを使用する言語での多重継承は、コンストラクタやコンストラクタチェーンの継承問題を悪化させ、これらの言語でメンテナンスや拡張性の問題を引き起こします。 大きく異なった構築方法による継承関係のオブジェクトは、コンストラクタの連鎖パラダイムの下で実装するのが難しいです。

COMとJavaインターフェイスのようなインターフェイス(純粋な抽象クラス)を使用するためにこれを解決する現代的な方法。

私はこれの代わりに他のことをすることができますか?

はい、できます。 私はGoFから盗むつもりです。

  • インプリメンテーションではなくインターフェイスへのプログラム
  • 継承よりも構成を優先する



複数の継承を「避ける」べきではありませんが、「ダイヤモンド問題」( http://en.wikipedia.org/wiki/Diamond_problem )などの問題を認識し、あなたに与えられた力を注意深く扱うべきですあなたはすべての力を持っているべきです。




すべてのプログラミング言語は、賛否両論のオブジェクト指向プログラミングのやり方が少し異なります。 C ++のバージョンは、パフォーマンスに重点を置いており、無効なコードを書き込むのは簡単ではないという付随する欠点があります。これは多重継承にも当てはまります。 結果として、この機能からプログラマーを離れる傾向があります。

他の人は、多重継承が何に良いものではないのかという問題に取り組んできました。 しかし、それを避ける理由が安全ではないということが多かれ少なかれ示唆されているという、かなりのコメントがあります。 はい、いいえ。

C ++でよくあることですが、基本的なガイドラインに従えば、常に「あなたの肩を見渡す」ことなく、安全に使うことができます。 重要なアイデアは、 "ミックスイン"と呼ばれる特別な種類のクラス定義を区別することです。 クラスはすべてのメンバ関数が仮想(または純粋仮想)である場合に混在します。 その後、あなたは1つのメインクラスと好きな数の "ミックスイン"から継承することができますが、ミックスインをキーワード "virtual"で継承する必要があります。 例えば

class CounterMixin {
    int count;
public:
    CounterMixin() : count( 0 ) {}
    virtual ~CounterMixin() {}
    virtual void increment() { count += 1; }
    virtual int getCount() { return count; }
};

class Foo : public Bar, virtual public CounterMixin { ..... };

私の提案は、クラスをミックスインクラスとして使うつもりなら、コードを読んでいる誰もが何が起こっているのかを見たり、基本的なガイドラインの規則で遊んでいることを確認したりするための命名規則を採用することです。 仮想基底クラスの仕組みのために、あなたのミックスインにもデフォルトのコンストラクタがあれば、もっとうまくいくことがわかります。 また、すべてのデストラクタを仮想化することも忘れないでください。

私がここで「ミックスイン」という言葉を使用しているのは、パラメータ化されたテンプレートクラスと同じではありません( このリンクを参照してください)。しかし、用語集を公正に使用していると思います。

今では、これが複数の継承を安全に使用する唯一の方法であるという印象を与えたくありません。 これは、チェックするのが簡単な単なる方法です。




エッフェル塔を使用しています。 私たちは優れたMIを持っています。 心配ない。 問題ありません。 簡単に管理できます。 MIを使用しない場合があります。 しかし、それは、A)それをうまく管理していない危険な言語で、B)彼らが何年も何年もMIの周りで働いてきたことに満足しているため、またはC)その他の理由(私はかなり確信しています - 上記の回答を参照してください)。

私たちのために、エッフェル塔を使用して、MIは他のものと同じくらい自然であり、ツールボックスのもうひとつの素晴らしいツールです。 率直に言えば、誰もエッフェル塔を使用していないことはまったく気にしていません。 心配ない。 私たちは私たちが持っているものに満足しています。

あなたが探している間:空の安全性とNullポインタ逆参照の根絶に特に注意してください。 私たちはすべてMIの中で踊っていますが、あなたの指針は失われています! :-)




ダイアモンドパターン以外に、多重継承はオブジェクトモデルを理解しにくくする傾向があり、メンテナンスコストが増加します。

構成は、本質的に理解し、理解し、説明するのが簡単です。 コードを書くのは面倒ですが、良いIDEです(Visual Studioで作業してから数年経ちましたが、Java IDEには構成ショートカットの自動ツールがあります)。

また、メンテナンスの面では、非文字継承インスタンスでも「ダイヤモンド問題」が発生します。 たとえば、AとBがあり、クラスCがそれらを拡張し、Aにオレンジジュースを作る「makeJuice」メソッドがあり、それを拡張して、ライムのひねりでオレンジジュースを作る:デザイナーが ' B 'は、電流を生成し、生成する' makeJuice 'メソッドを追加します。 'A'と 'B'は現在両親と互換性があるかもしれませんが、それは彼らがいつもそうであるという意味ではありません!

全体的に、継承を避ける傾向の最大点、特に多重継承は健全です。 すべての格言は例外ではありますが、あなたがコードしている例外を指し示す点滅するネオンサインがあることを確認する必要があります(そして、あなたの脳を訓練してください。サイン)、あなたはそれが一度にすべて意味をなすことを確認することを確認してください。




継承に優先して合成を使用できます。

一般的な感想は、構成がより良いことであり、非常によく議論されています。




Related