2012-05-11 5 views
8

こんにちは私はテンプレートと多型に関して疑問があります。定義によって、多形性はコードの再利用性を提供し、テンプレートはある意味で、異なるデータ型の汎用プログラミングを提供することによって、同じコードを使用することができます。だから、テンプレートに対して多型を使うことのメリットは何ですか?それは愚かな質問かもしれませんが、私は正確な違いを知ることが好奇心です。テンプレートと多型の違いは何ですか

+1

テンプレートは静的/コンパイル時の多態性を提供します。 * virtualism *は動的な多形性を提供します。 –

+1

は何が違うのですか?すべて。多態性は、コードの再利用性に関して遠隔からではありません。テンプレートは。 –

+1

@MooingDuck:多態性はコードの再利用を可能にします。新しいコード(同じ基底クラスの方に書かれている)を使って、古いコード(多態的な基底クラスに対して書かれている)。 –

答えて

11

あなたは多型が何であるか誤解しているようです。

多態性は、そのコアで、派生クラスとは関係がありません。多態性とは、単に型を知ることなく型を使う能力を意味します。具体的な型を使用するのではなく、多型は何らかの型のプロトタイプに依存して、どの型を取るかを定義します。そのプロトタイプに合ったどんなタイプも受け入れられます。

ランタイムポリモーフィズムは、仮想関数を含む基本クラスからクラスを派生させることによって提供されます。基本クラスと仮想関数は、多形プロトタイプを形成します。これらの仮想関数を呼び出す基本クラスを受け入れるように記述されたコードは、クラスインスタンスを基底クラスから派生したものを受け入れます。

コンパイル時多型が起こる...コンパイル時に多型である。)これが意味することは、コンパイラが何が起こっているかを知っていなければならないということです。多相プロトタイプに対してC++コードを書いているかもしれませんが、コンパイラは気にしません。コンパイル後に特定の具体的なタイプが得られます。

コンパイル時の多型は、C++のテンプレートによって提供されます。テンプレート関数またはクラスは、通常「概念」と呼ばれるプロトタイプに準拠する任意の型を取ることができます。基本クラスおよび仮想関数とは異なり、プロトタイプは暗黙的です。プロトタイプは、型関数がテンプレート関数/クラスによってにどのように使用されるかによってのみ定義されます。

このテンプレート機能がある場合:

template<typename T> 
void Stuff(T &t) 
{ 
    t.call(15); 
} 

T暗黙の要件があります。この要件は、callと呼ばれるメンバ関数を持つことです。整数値で呼び出すことができるこのメンバ関数の単一のオーバーロードが存在する必要があります。

これは、このプロトタイプに適合するタイプのが使用可能であることを意味します。

テンプレート多型は、より広範な型の配列で使用できるため、継承多型よりも広いです。型は、継承多型を使用するように特別に設計されていなければなりません。あなたはクラスから派生しなければなりません。型は、テンプレートの多形性に適応する非破壊的(つまり、型自体を変更する必要はありません)でもかまいません。テンプレートのプロトタイプがうまく設計されている場合でも、moreso:Stuffのこのバージョンが必要と

template<typename T> 
void Stuff(T &t) 
{ 
    call(t, 15); 
} 

すべてがT&を取り、いくつかの機能と整数値が存在することです。私がStuffで使用したいタイプがある場合、適切な名前空間(つまり、そのタイプが定義されている名前空間)にcall関数を定義するだけです。そして、これはうまくいくでしょう。すべてを除き、の型自体を変更します。

もちろん、コンパイル時の多型は...コンパイル時です。ユーザー入力やデータファイルで多型を選択したい場合は、テンプレートが大いに役立つことはありません(型消去、テンプレートベースのテクニックが役立ちます)。実行時の多形性の主な利点は、それが本当に実行時であることです。

もう1つの利点は、プロトタイプがより正確であるということです。継承についてすべて明示されています。基本クラスの仮想関数インタフェースは明確にレイアウトされています。コンパイラーは、その基本クラスを誤って使用しようとするのを止めます(存在しないメソッドを呼び出します)。確かに、まともなIDEはあなたのコードを導くので、基本クラスのメソッドしか見ることができません。

テンプレートの多型性は、より暗黙的です。 C++は、特定のテンプレート関数/クラスが型に置くプロトタイプを記述する方法がないので、誤って呼び出すべきではないテンプレート型で何かを呼び出すのは非常に簡単です。コンパイラは、プロトタイプに適合しない型を使用しようとすると、これを検出します。そして、その場合でも、一般的には、テンプレートコードがどの程度深く入れ子になっているかによっては、どこに問題があるのか​​を知るのが難しいという大規模なエラーが発生します。

暗黙的なテンプレートのポリモフィックプロトタイプを実装することは、スペルミスがないため、さらに難しくなります。派生クラスを実装するには、基本クラスを歩き回り、すべての仮想関数を調べて実装する必要があります。テンプレートプロトタイプでこれを行うのは、どこかに書類がある場合を除き、はるかに難しいです。あなたが何かを実装することに失敗した場合、あなたはもう一度、問題について来るよりも一般的ではないエラーを得るでしょう。

+1

"このメンバ関数の整数値で呼び出すことができる単一のオーバーロードが必要です。" - そして 'int'を使った呼び出しはあいまいであってはならず、おそらく私が忘れてしまったいくつかの他の条件であってはなりません。そのため、多形プロトタイプは、通常、「この式は次のプロパティを持つ必要があります:...」という観点から文書化されています。どの関数やオーバーロードが存在するかを文書化しようとすると、あらゆる種類のエッジケースに入ります。 –

関連する問題