17

こんにちは、テンプレートとポリモーフィズムについて疑問があります。ポリモーフィズムは定義上、コードの再利用性を提供し、ある意味では、テンプレートを使用すると、異なるデータ型の汎用プログラミングを提供することで、ユーザーは同じコードを使用できます。では、テンプレートよりもポリモーフィズムを使用する利点は何でしょうか。ばかげた質問かもしれませんが、正確な違いを知りたいです。

4

2 に答える 2

24

あなたはポリモーフィズムが何であるかを誤解しているようです。

ポリモーフィズムは、本質的に、派生クラスとは何の関係もありません。ポリモーフィズムとは、タイプについてすべてを知らなくてもタイプを使用できることを意味します。ポリモーフィズムは、具体的な型を使用するのではなく、何らかの形式のプロトタイプに依存して、どの型をとるかを定義します。そのプロトタイプに適合するすべてのタイプが受け入れられます。

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

コンパイル時のポリモーフィズムは、コンパイル時に発生するポリモーフィズムです;)これは、コンパイラが何が起こっているかを知っている必要があることを意味します。ポリモーフィックプロトタイプに対してC++コードを記述したかもしれませんが、コンパイラは気にしません。コンパイル後に特定の具体的なタイプを取得します。

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

このテンプレート関数がある場合:

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

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

これは、このプロトタイプにたまたま適合する任意のタイプを使用できることを意味します。

テンプレートポリモーフィズムは、より幅広い型の配列で使用できるため、継承ポリモーフィズムよりも幅広いです。タイプは、継承ポリモーフィズムを使用するように特別に設計する必要があります。クラスから派生する必要があります。タイプは、テンプレートのポリモーフィズムに非破壊的に適合させることができます(つまり、タイプ自体を変更する必要はありません)。テンプレートプロトタイプが適切に設計されている場合はさらに次のようになります。

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

このバージョンでStuff必要なのは、T&と整数値をとる関数があることだけです。で使用したい型がある場合、私がしなければならないのは、適切な名前空間(つまり、型が定義された名前空間)で関数をStuff定義することだけです。callそして、これはうまく機能します。タイプ自体を変更せずにすべて。

もちろん、コンパイル時のポリモーフィズムは...コンパイル時です。ユーザー入力またはデータファイルでポリモーフィック型を選択したい場合、テンプレートはあまり役に立ちません(ただし、型消去、テンプレートベースの手法は役立ちます)。ランタイムポリモーフィズムの主な利点は、それが実際にランタイムであるということです。

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

テンプレートのポリモーフィズムは、はるかに暗黙的です。C ++には、特定のテンプレート関数/クラスが型に配置するプロトタイプを綴る方法がないため、テンプレート型で誤って呼び出すべきではないものを誤って呼び出すことは非常に簡単です。プロトタイプに適合しないタイプを使用しようとした場合にのみ、コンパイラーはこれを検出します。その場合でも、通常、(テンプレートコードがどれだけ深くネストされているかに応じて)大量のエラーが発生し、問題がどこにあるかを知ることが困難になります。

また、暗黙のテンプレート多形プロトタイプを実装することは、詳細に説明されていないため、非常に困難です。派生クラスを実装するには、基本クラスをウォークスルーし、すべての仮想関数を調べて、それらを実装する必要があります。テンプレートのプロトタイプに対してこれを行うことは、それを詳しく説明しているドキュメントがどこかにない限り、はるかに困難です。何かを実装しなかった場合は、問題についての発表よりも一般的に少ないエラースピューが発生します。

于 2012-05-11T18:04:43.497 に答える