[C++] テンプレートの詳細な紹介 - 関数テンプレート、クラス テンプレート


ヾ(๑╹◡╹)ノ「人は常に過去の怠惰の代償を払わなければなりませんヾ(๑╹◡╹)ノ」
写真の説明はXiao Liu Shuです


1. 汎用プログラミング

汎用プログラミング: 型とは関係のない汎用コードを記述することは、コードを再利用する手段です。テンプレートは汎用プログラミングの基礎です。[特定のタイプではありません]
テンプレート テンプレート キーワード
template<class T>
template<typename T>

  • テンプレート パラメーターの学習は、関数パラメーターと比較できます。
  • テンプレートパラメータは型を渡し、関数パラメータはオブジェクト値を渡します。
  • テンプレートの定義と宣言は、2 つのファイルに別々に存在することをサポートしていません [リンク エラーが発生し、すべてのリンク エラーはシンボル テーブルが見つからないことが原因です]。これは、コンパイラのテンプレート T が決定できず、シンボル テーブルが見つからないためです。生成される。
  • テンプレートは、.h および .cpp での宣言と定義をそれぞれサポートしていないため、通常は 1 つのファイルに配置する必要があります。一部の場所は .hpp という名前になります (ヘッダー ファイルと定義の実装内容がマージされます) が、.hpp である必要はなく、.h も可能です。

対処方法【宣言と定義が分離してリンクエラーが発生する】

  1. 表示インスタンス化仕様(面倒なので非推奨)
//声明
template
void Swap<int>(int& left, int& right);

template
class Vector<int>;

template
class Vector<double>;
//原因是因为声明没有类型,那么我们就把类型给写出来
  1. 2 つのファイルを分離せずに

2. 関数テンプレート

2.1 関数テンプレートの概念

関数テンプレートは関数ファミリーを表します。関数テンプレートは型とは関係がありません。使用時にパラメータ化され、実際のパラメータの型に従って関数の特定の型バージョンが生成されます。

2.2 関数テンプレートの形式

template<typename T1, typename T2,...,typename Tn>
戻り値 type 関数名 (パラメータリスト) {}

template<typename T>//也可以是class T
void Swap(T& left, T& right)
{
    
    
	T tmp = left;
	left = right;
	right = tmp;
}
//函数模版

: typename はテンプレート パラメーターのキーワードを定義するために使用され、クラスも使用できます (注意: 構造体をクラスの代わりに使用することはできません) [スワップ ライブラリにはそれがあるため、自分で実装する必要はありません]
宣言と定義

//声明
template<typename T>
void Swap(T& left, T& right);

//定义
template<typename T>
void Swap(T& left, T& right)
{
    
    
	T tmp = left;
	left = right;
	right = tmp;
}
//函数模版

定義の記述形式に注意

2.3 関数テンプレートの原理

コンパイラのコンパイル段階では、テンプレート関数を使用するために、コンパイラは、で渡される実際のパラメータの型に応じて、呼び出しに対応する型の関数を推測して生成する必要があります。【通話は同じ機能ではありません】

関数テンプレートの型は、仮パラメータに渡された実際のパラメータに基づいてコンパイラによって推定されます。自動的に推定できない場合は、インスタンス化を表示し、テンプレート パラメーターを指定する必要があります。
クラス テンプレートの型は明示的にインスタンス化され、明示的に指定されます。

2.4 関数テンプレートのインスタンス化

関数テンプレートが異なる型のパラメーターとともに使用される場合、それは関数テンプレートのインスタンス化と呼ばれます。
テンプレートパラメータのインスタンス化は、暗黙的なインスタンス化明示的なインスタンス化に分けられます。
1. 暗黙的なインスタンス化: 仮パラメータに渡された実際のパラメータに従って、コンパイラにテンプレート パラメータの実際の型を推定させます。

template<typename T>//也可以是class T
void Swap(T& left, T& right)
{
    
    
	T tmp = left;
	left = right;
	right = tmp;
}
//函数模版

int main()
{
    
    
	int a = 1;
	int b = 2;
	Swap(a, b);//编译器根据实参传递给形参,判断为int
	double c = 1.2;
	double d = 2.3;
	Swap(c, d);//编译器根据实参传递给形参,判断为double
	return 0;
}

パラメータの型が異なる場合:

template<typename T>
T Add(const T& left, const T& right)//常量,需要有const
{
    
    
	return left + right;
}
int main()
{
    
    
	int a = 1;
	double c = 2.1;
	Add<int>(a, c);//c这里有一个隐式类型转换
	Add<double>(a, c);

	Add(a,(int)c);//c这里有一个隐式类型转换
	Add((double)a, c);
	return 0;
}

2. 明示的なインスタンス化: 関数名の後の <> 内にテンプレート パラメーターの実際の型を指定します。

template<typename T>
T* func(int n)
{
    
    
	terurn new T[n];//new n个对象,,,,无法推导出T的类型
}
int main()
{
    
    
	int* p1 = func<int>(10);//函数模版显示实例化
	return 0;
}

型が一致しない場合、コンパイラは暗黙的な型変換を実行しようとし、変換が失敗するとエラーを報告します。

関数テンプレートの型は、仮パラメータに渡された実際のパラメータに基づいてコンパイラによって推定されます。自動的に推定できない場合は、インスタンス化を表示し、テンプレート パラメーターを指定する必要があります。

2.5 関数テンプレートのマッチング原則

  1. 非テンプレート関数[特殊関数]は、同じ名前の関数テンプレートと同時に存在することができ、関数テンプレートをこの非テンプレート関数としてインスタンス化することもできます
  2. 非テンプレート関数と同じ名前の関数テンプレートの場合、他の条件が同じ場合、非テンプレート関数が最初に呼び出され、呼び出し時にテンプレートからインスタンスは生成されません。テンプレートがより適切に一致する関数を生成できる場合、そのテンプレートが選択されます。
  3. テンプレート関数では自動型変換はできませんが、通常の関数では自動型変換が可能です。

3、クラステンプレート

3.1 クラステンプレートの定義

template<クラス T1, クラス T2, ..., クラス Tn>
class クラステンプレート名
{ // クラスメンバ定義};

クラス テンプレートは具体的なクラスではなく、インスタンス化は実際のクラスです。

template<class T>
class Stack
{
    
    
public:
    // 使用析构函数演示:在类中声明,在类外定义。
	~Vector();
	//……
	void push(T x)
	{
    
    

	}

private:
	T* _a;
	int _top;
};
//类模板中函数放在类外进行定义时,需要加模板参数列表,每一个函数都需要加模板参数列表
template <class T>
Vector<T>::~Vector()
{
    
    
if(_pData)
     delete[] _pData;
_size = _capacity = 0;
}

int main()
{
    
    
	Stack<int> s1;
	s1.push(1);
	Stack<double> s2;
	s2.push(2.1);
	return 0;
}

クラステンプレート内の関数がクラス外で定義されている場合、テンプレートパラメータリストを追加する必要があります

3.2 クラステンプレートのインスタンス化

クラス テンプレートのインスタンス化は、関数テンプレートのインスタンス化とは異なります。クラス テンプレートのインスタンス化は、クラス テンプレート名の後に <> を付け、インスタンス化された型を <> 内に置く必要があります。クラス テンプレート名は実際のクラスではなく、インスタンス化されたものです。結果は次のようになります。本当のクラス。

ベクター クラス名、Vector<int> はタイプ Vector<int>s1; Vector<double>s2;


要約する

本日の内容は以上ですが、この記事では関数テンプレートとクラステンプレートについて詳しく紹介します。友達を助けたいと思っています!

おすすめ

転載: blog.csdn.net/m0_57388581/article/details/132513921