3

複数のクラス(継承を使用)を持つアプリケーションがあるとします 今、ある日、アプリケーションに新しい仕様を追加する必要があります。多重継承。DIAMOND現在のアプリケーションの機能を拡張したいとき

例えば、このコード:

class A{}; 
class B : public A{}; 
class C : public A{}; 

は今、私の新しい機能は、これを行うために私が必要になります。

class D{} : public B,public C{}; 

しかし、これはダイヤモンドの問題につながります。

この問題を克服する方法: 1)ベストプラクティスとして、将来的に複数の継承を使用する必要があると仮定して、すべてのクラスに仮想継承を使用しますか? または 2)コードを変更して、必要に応じてベースクラスを仮想的に変更します。

+0

あなたの** Y **継承は問題ではありません。 'D 'を' A'と脅かす必要がありますか? – Jarod42

+0

仮想継承には、特に階層全体で必要なコンストラクタに対して強い制約があります。 – Jarod42

+1

ご覧になりましたか(http://stackoverflow.com/a/407928/2721583)?コードを変更して、具象基底クラスの代わりにインターフェイスを使用することができます。 –

答えて

1

この問題を克服する良い方法の1つは、クラスから取得しようとしている動作をコンポーネントに分離することです。

は今、あなたはこの

class A {} 
class B : public A {some behavior X} 
class C : public A {some behavior Y} 
class D : public ? {I need X and Y plus some behavior Z} 

ワン(潜在的に悪い)これはただ単にあなたが他から必要な行動をコピーし、その後BまたはCから拡張することで解決する方法が、このような状況を持っていますコードを複製しています。あなたが行うことができるかもしれません何

は、コンポーネントにあなたの行動をすることです。これは、我々はインターフェイスを呼び出すことができます純粋仮想クラスになり

class Behavior {void behave() = 0} 

。その後、行うことができます:

class D : public A {BehaviorX, BehaviorY, BehaviorZ, ...} 

あなたが本当にコンポーネントモデリングを取るしたい場合:あなたはAから延びる新しいクラスを作るが、あなたがピックアップし、彼らが持っているビヘイビアを選択できに

class BehaviorX : public Behavior {void behave(){behavior x}} 
class BehaviorY : public Behavior {void behave(){behavior y}} 
class BehaviorZ : public Behavior {void behave(){behavior z}} 

これができるようになりますあなたが夢見ることができる任意の数の行動を使用することができるコンポーネントバッグとしてクラスAを使用すると、次のレベルに子供クラスをなくすことができます。あなたが望むふるまいを持ってください:

A likeB = new A(BehaviorX); 
A likeC = new A(BehaviorY); 
A likeD = new A(BehaviorX, BehaviorY, BehaviorZ); 
A likeE = new A(BehaviorY, BehaviorZ, Behavior?); 
関連する問題