2011-07-12 7 views
17

多くの状況では、テンプレートは提供できない必須の機能を継承していることがあるので、質問自体は尋ねません。たとえば、1つの基本型(多型性)で異なる型を扱う必要がある場合、継承を使用する必要があります。継承の代わりにテンプレートを使用するのはいつですか?

しかし、問題は継承とテンプレートの両方で解決できる場合があります。

コードの特定の部分の例戦略パターンのようなパラメータ化のために取る:ファイルパーサーの

一つの解決策は、次のようになります。

class FileParser 
{ 
    //... 
    public: 
     void Parse(ParsingAlgorithm* p); 
    //... 
} 

void FileParser::Parse(ParsingAlgorithm* p) 
{ 
    m_whatevertypeofvaluesineed = p->Parse(whateverparametersyouneed); 
} 

ParsingAlgorithmは、抽象基底クラスであり、いくつかの基本的なメソッドを提供し、FileParserクラス用の特定のパーサーを実装するのが好きな人が継承する必要があります。

しかし、同じことが簡単にテンプレートを使用して達成することができます。

template <class Parser> 
class FileParser 
{ 
    //... 
    public: 
     void Parse() 
     { 
      m_whatevertypeofvaluesineed = m_parser.Parse(whateverparametersyouneed); 
     } 

    private: 
     Parser m_parser; 
    //... 
} 

は、私は、テンプレートや継承を使用するかどうかを決定するために使用できるいくつかの一般的なルールはありますか?あるいは、仮想関数などの実行時のオーバーヘッドを避けるために、可能な限りテンプレートを使用するだけですか?継承によって提供さ実行時ポリモーフィズムとは対照的に、

+0

[CRTPは小さなデザインでは仮想機能を完全に置き換えることができますか?](http://stackoverflow.com/questions/6613779/can-crtp-completely-replace-virtual-functionality-for-smaller-designs) – iammilind

答えて

17

コンパイル時にどのオブジェクトを操作しようとしているのか知っていれば、テンプレートを使った静的な多形性はしばしば最速の方法です。明示的な継承を必要としないコードを生成します。また、強力なクラス階層に制限されていないので、より汎用的である場合もあります。

実行時の多態性が必要な場合は、ポインタ、継承、および仮想関数のわずかなオーバーヘッドを使用する以外に選択肢はありません。

私自身の意見:

  • 使用テンプレートの可能な、それはコードをfactoriseする快適
  • 利用の継承(しかし異種のコレクションを持っていない)ですが、スライシングに注意してください。
  • 時々、あなたは選択の余地を持っていない、あなたが
4

テンプレートはコンパイル時のポリモーフィズムを提供しています。私はできればテンプレートを使うほうが好きです。

この記事ではTemplates and Inheritanceについて詳しく説明しています。

-1

私の提案は、この場合どちらも使用せず、ファイルタイプごとに別々の機能を使用することです。

Stream stream = open(filepath); 

    Image image = ParseBMP(stream); 
    // ...or 
    Image image = ParseJPG(stream); 

物事を複雑にする必要はありません。

+0

あなたは正しいですが、私の例は、「継承対テンプレート」の問題が発生する可能性のあるタイプの状況のすばやい例であるはずです。 – TravisG

+0

私は同意しません。さまざまな機能を使用することは、オープン・クローズ・プリンシパルに対して行われます。http://en.wikipedia.org/wiki/Open/closed_principle –

+0

以前にそのプリンシパルについて聞いたことはありませんでしたが、それは私には悪いようです。 –

3

テンプレートは、より以来、実行時に一般的に、よりパフォーマンスのあるポインタを使用することの痛みを中心にドラッグhetergenousコレクションをする仮想呼び出し

  • のパフォーマンスの問題を心配しないでくださいコンパイル時に作業が行われます。一方、それらはより複雑であり、したがって、記述し理解することは困難であり得る。だから、が解決策全体を過度に複雑化しない場合は、いつでもそれらを使用することをお勧めします。

    例の場合、機能的には同等ではありません。最初の変更ではは実行時にパーサーのインスタンスを作成する必要がありますが、2番目の変更ではプログラマーがコードを書くときにパーサーを選択する必要があります。

  • 関連する問題