2017-01-10 10 views
1

純粋な仮想メソッドメソッドのセットを持つ抽象クラスを作成しました。これらのメソッドの具体的な実装を持つ3つのクラスがあります。純粋仮想メソッドと仮想メソッドを混在させたクラス

上記の構造を書いた後、派生クラスのメソッドのいくつかが同じ実装を持つことがわかりました。そこで、私はこれらの関数の基本クラスのロジックに移動し、の代わりに仮想の純粋な仮想としました。さて、実装は派生クラスで繰り返す必要はありません。これはコンパイルして正常に実行します。

私の基本クラスは、純粋な仮想メソッドと仮想メソッドが混在しています。このような構造に従うのは良い設計アプローチですか?

+1

なぜ基本クラスは純粋仮想メソッドしか持つことができないと思いますか? –

+0

はい、それはまったく問題ありません。あなたがそれをインスタンス化することができないので、それが1つ以上の純粋な仮想を含んでいる限り、それは依然として抽象基本クラスですが、一般的な機能をそこに移動することは良いことです。 –

+2

本当にあなたのルートインターフェースを完全に純粋なものにしたいのであれば(例えば、ダイナミックなファクトリlib内の実装を完全に隠す)、純粋仮想インターフェースを継承し、共通コードを実装し、残りの純粋なものを再確認する中間BaseImplを実装することもできますバーチャル、あなたのコンクリートファイナルは*から*継承することができます。 – WhozCraig

答えて

0

はい、問題ありません。ただし、これらがすべてのクラスである場合、基本クラスの実装をvirtualにする必要はありません。

+2

のITYMに同意します。 ;-) –

+1

はい、いいえ。これらのクラスがパブリックAPIの一部である場合、またはバイナリの後方互換性が必要な場合は、将来のことを念頭に置いて設計してください( 'virtual')。それ以外の場合は、要件が変更された場合に後でメソッドを仮想にすることができます。 –

5

あなたはクラスで唯一あなたの純粋仮想関数がインタフェースの多いものとしてみなされるべきですべてを置く場所のパターンが出現しているように見えるんが、それは、絶対に大丈夫です。

のインターフェイスの「共通」部分を実装するクラスを定義し、そのクラスから3つのクラスを継承させることができます。

これは、スケーラビリティとメンテナンスが容易なコードに適しているようです。

Javaでは、このパターンの使用はかなりの負担となります。

1

明らかに、クラス間の関係によって異なります。言い換えれば、それは設計または実装の選択です(つまり、あなたがそれを賢明に正当化できる限り、あなた次第です)。技術的には、クラスが仮想、純粋仮想、非仮想、および静的メンバー関数を混在させることを妨げるものは何もありません。

2つの派生クラスが継承された仮想関数をオーバーライドし、同じ方法で実装する場合、 - はい - 私は真剣にその関数をベースクラスに提供することを検討します。しかし、派生したすべてのクラスがその関数の実装にデフォルトすることが理にかなっているかどうかなど、私が尋ねる疑問がたくさんあります。コードの再利用の観点からは、そのようなことは意味をなさないかもしれません。デザインの観点からは、そうではないかもしれません。

つまり、関数の特定の実装を「デフォルト」として扱うことが理にかなっているとします(つまり、その関数をオーバーライドしない限り、すべての派生クラスはデフォルトで使用されます)。基本クラス。あなたが意味をなさない示唆、両方の派生クラスが同じManoeuvre()の機能を持っていたこと、なぜなら私達のモデリングの忠実度、この

class Aircraft 
    { 
     public: 
      virtual void Manoeuvre() = 0; 
    }; 

    class Hornet : public Aircraft // F/A-18 hornet fighter aircraft 
    { 
     public: 

       void Manoeuvre(); 
    }; 

    class Tomcat : public Aircraft // F-14 tomcat fighter aircraft 
    { 
     public: 

       void Manoeuvre(); 
    }; 

だがそれを言ってみましょう考えるの粗例として

- 彼らは、両方とも超音速戦闘機である(おそらく、異なるパラメータ設定であっても、同様の操縦様式を採用するだろう)。しかし、それはこの場合には、そのような

class Hercules : public Aircraft // C-130 hercules cargo plan 
    { 
     public: 

       void Manoeuvre(); 
    }; 

として超音速戦闘機、されない航空機があるのでHerculesが操縦を継承するために、それは意味がありません、基底クラスへのManoeuvre()機能を移動するのに十分ではありません超音速戦闘機の能力、またはその逆。したがって、これがAircraftクラスによって供給されることは意味をなさない。この場合

、Iは中間体(HornetTomcatはなくHerculesの共通ベースとすることができる)ようFighterなどのクラス、および導入考慮するかもしれない - おそらくCargoPlane - Iは、貨物航空機の複数のタイプを表すように求められた場合それらの共通基盤となること。その後、FighterCargoPlaneの両方がAircraftから派生する可能性がありますが、Aircraftは、一部の機種にのみ意味をなさない機能を提供していません。

偶然のコメント:何人かの人々は別のことを主張しますが、純粋な仮想関数が定義(実装)するのを妨げるものはC++には何もありません。意味は、派生クラスによって関数をオーバーライドする必要がありますが、基本クラスによって提供されるデフォルト定義(派生クラスの関数で明示的に呼び出すことができます)があります。

関連する問題