2012-09-26 13 views
5

私はクラスAとBを持っています。今では、AとBの両方でいくつかのフィールドとメソッドを使用するが、それらのすべてではない新しいクラスCを書く必要があります。 (私はAとBからのものの約50%を使用します)。コードの再利用のための継承C++

今私はAとBの両方から継承することを考えていますが、それは意味を持たない多くのフィールドとメソッドがCに含まれるようになります。そう私は

AとB

からコードの行数をコピー&ペーストする必要がありますので、基本的に私は、唯一のコードの再利用のために継承を使用してい

は、このような行為は本当に悪いですか?別の方法がありますか?

ありがとうございます!

+0

返信いただきありがとうございます!本当に感謝しています。私がAとBのいくつかの振る舞いを修正する必要があるため、継承を使用することを考えたのは、AとBを実際に編集したくないからです。 – user1657624

答えて

2

悪いです。論理的に意味があるときだけ、継承を使用してください。代わりに

使用組成物(private継承は組成物の形態であるが、より良い古い学校に行く):

class C 
{ 
    A a; 
    B b; 
} 

CABで構成されていない場合は、あなたもそう、代わりにポインタを維持することができますCのサイズは増加しません。

3

継承は、 "is a"パラダイムを使用する必要があります。
CがAとBのようなものであれば、A、Bから継承するという意味です。
すでに複数の継承を使用している場合は、AとBを複数のクラスに分割して、コードを作成し、必要なものだけからCを継承します。この方法では、Cは必要な領域だけを占有します(AとBにはメンバーが多いと仮定します)。
クラスのサイズはメンバーメソッドの影響を受けず、メンバーデータのみが影響を受けます。

+1

C++では、* public *継承は "is-a" 。他のレベルの継承は、「実現されたものである」のように...何か異なることを意味します。 – cHao

+0

@cHao - それは本当ですが、私的継承であっても、必要のないコードの部分にアクセスできるCは悪い習慣です。さらに、AとBに多くのデータメンバーがある場合、Cのサイズはそれよりも大きくなります。 –

6

継承には「半分です」という概念がないため、ここに行く方法は間違いありません。それは作曲の主要なケースのように聞こえる。

ABは、半分がそれぞれCを構成するのに十分であるため、複数の「機能」を持っているようです。

私は、これはあなたのケースにも適用可能であるわからないんだけど、二つの部分、A1Cに必要な機能を持つA1A2に侵入考えます。次にBについてはB1B2に同じ操作を行います。

A次いでA1A2の組成になり、BA1B1の組成になりB1B2Cの組成物であろう。不必要な機能やデータを持つものはありません。

3

ハーブサッターとアンドレイアレキが彼らの本C++ Coding Standards (item 34)で説明したよう、継承は、C++を使用すると、2つのクラスの間で使用することができます最も緊密な関係の一つである - それが唯一のクラス間の関係friendに2番目です。

S.O.L.I.D principles of OOによると、成功した設計は、クラス間の結合を緩和することを目的とする必要があります。これは、依存関係を最小限に抑えることを意味します。これは継承が慎重に使用すべきツールであることを意味します。もちろん

、依存関係は、一般的にどこか、その合理的な妥協点はすべて(例えば、C#やJavaなどの言語でinterface Sいわゆるに類似)で無実装したクラスから継承することができが存在する必要があります。例えばこのアプローチで

class IDriveable 
{ 
public: 
    virtual void GoForward() = 0; 
    virtual void GoBackward() = 0; 
}; 

class Car : public IDriveable { /* etc. */ }; 
class Bus : public IDriveable { /* etc. */ }; 
class Train : public IDriveable { /* etc. */ }; 

、あなたはいくつかの走行可能クラス間で再利用されているコードの要素を持っている場合、あなたは通常、繰り返しコードを排除するための組成物または他のいくつかの弱い関係を使用します。
おそらくあなたはBusCarためTurnLeftにコードを再利用したいが、Train左旋回は非論理的であるので、TurnLeftは、メンバーのBusCarある別のクラスで終わる可能性がありません。また

  • 、漠然と関連クラスのすべてについて知っておく必要があるかもしれない任意の機能は、インターフェイス/ベースではなく、核心ザラザラ実装の詳細だけを認識し、クラス階層構造の外部になります。

最終的な結果は、構成のための少量の余分なコードであることがありますが、設計が複雑であることが少なく、通常は管理が容易なものです。あなたが解決しようとしているユニークな問題に完全に依存しているので、このようなコードを設計するための厳格な規則はありません。

はあまりにも密結合せずにコードを再利用する他の方法があります - 非常に良いことですが、彼らは文法的にある - テンプレートを使用すると、暗黙的に純粋なvirtual機能を(テンプレートが追加型の安全性を提供含む空のクラスなしのインタフェースを定義してみましょう少し複雑です)。

さらに機能的なスタイルでコードを再利用するために、std::functionとlambdaを使用する方法があります。通常、関数オブジェクトを渡すときには、密接な依存関係はありません。これに代えて

0

は、それはあなたのコードをリファクタリングから利益を得ることができるように聞こえる

class A 
{ 
    virtual void foo(); 
    virtual void bar(); 
}; 

class B 
{ 
    virtual void biz(); 
    virtual void baz(); 
}; 

class C : public A, public B 
{ 
    virtual void foo() { /* my stuff */ } 
    virtual void biz() { /* my other stuff */ + 

    // but I don't need bar or baz! 
}; 

が分割うち、あなたがCにしたいAとBの概念的に異なる部分考えてみましょう:

class core_A 
{ 
    virtual void foo(); 
}; 

class A : public core_A 
{ 
    virtual void bar(); 
}; 

class core_B 
{ 
    virtual void biz(); 
}; 

class B : public core_B 
{ 
    virtual void baz(); 
}; 

class C : public core_A, public core_B 
{ 
    virtual void foo() { /* my stuff */ } 
    virtual void biz() { /* my other stuff */ + 

    // Great, I don't have bar or baz! 
};