記事ディレクトリ
1. 関数テンプレート
1. 関数テンプレートとは何ですか?
簡単に言えば、関数テンプレートはテンプレートであり、関数パラメータの型とは何の関係もありません。これは型であり、実際の関数ではありません。インスタンス化された関数は、実際のパラメータの型に従って型を自動的に推測します。
2. 関数テンプレートの形式
template<typename T1,typename T2...>
返回值类型 函数名(参数列表)
{
}
3. 関数テンプレートの原則
関数テンプレートは実際の関数ではなくテンプレートであり、渡された実パラメータの型に応じて特定の関数をインスタンス化するもので、繰り返したことをコンパイラに渡すのと同じです。
例えば:
template<typename T>
T Add(const T& a1, const T& a2)
{
return a1 + a2;
}
int main()
{
int a = 10, b = 20;
double c = 3.14,d = 2.11;
cout << Add(a, b) << endl;
cout << Add(c, d) << endl;
return 0;
}
加算操作を実行するための加算関数の関数テンプレートを定義します。関数テンプレートは、渡した実際のパラメータの型に応じて異なる Add 関数を自動的にインスタンス化し、これらの関数は関数のオーバーロードを構成します。
4. 関数テンプレートのインスタンス化
(1) 暗黙的なインスタンス化
簡単な例を挙げると、
定義する関数テンプレートでは、テンプレート パラメーターの型が 1 つだけ指定されていますが、実際のパラメーターの型は 2 つ異なる場合があります。
template<typename T>
T Add(const T& a1, const T& a2)
{
return a1 + a2;
}
int main()
{
int a = 10;
double b = 20.3;
cout << Add(a, b) << endl;
return 0;
}
型が 1 つしかない関数テンプレートに、2 つの異なる型の実パラメータが同時に出現する場合、コンパイラはインスタンス化にどの実パラメータの型が使用されるかを確認できません。
解決:
int main()
{
int a = 10;
double b = 20.3;
cout << Add((double)a, b) << endl;
cout << Add(a, (int)b) << endl;
//可能存在精度丢失的情况
return 0;
}
暗黙的な型変換により、コンパイラが認識できない状況を解決できます。
(2) 表示のインスタンス化
template<typename T>
T Add(const T& a1, const T& a2)
{
return a1 + a2;
}
int main()
{
int a = 10;
double b = 20.3;
cout << Add(a, b) << endl;
return 0;
}
この場合、別の解決策があります。
int main()
{
int a = 10;
double b = 20.3;
cout << Add<int>(a, b) << endl;
return 0;
}
このような方法は明示的なインスタンス化と呼ばれ、現実には明示的なインスタンス化が必要な状況に遭遇することはほとんどありませんが、次のような状況では明示的な強度が必要です。
template<class T>
T* Alloc(int n)
{
return new T[n];
}
int main()
{
Alloc<double>(10);
return 0;
}
この場合、関数テンプレートの型を使用していないため、引数 n を渡すだけでは T の型を推定できません。その場合は、明示的なインスタンス化を使用する必要があります。
2. クラステンプレート
1. クラステンプレートの定義形式
template<class T1, class T2, ..., class Tn>
class 类模板名
{
// 类内成员定义
};
2. クラステンプレートのインスタンス化
知らせ:
通常クラスの型とクラス名は同じですが、
テンプレートクラスの型とクラス名は異なります
クラス テンプレートのインスタンス化は、関数テンプレートのインスタンス化とは異なります。クラス テンプレートのインスタンス化では、クラス テンプレート名の後に <> を付け、インスタンス化された型を <> 内に置く必要があります。
クラス テンプレート名は実際のクラスではありませんが、インスタンス化の結果は実際のクラスです。
例えば:
// string类名,string<int>才是类型
string<int> s1;
string<double> s2;
1. クラステンプレート、関数テンプレートを問わず、その動作範囲は直後のクラス/関数です。
つまり、{} を見てください。
2. クラス テンプレート内の関数がクラスの外部で定義されている場合、テンプレート パラメーター リストを追加する必要があります。
例:
template<typename T>
class Stack
{
public:
Stack(size_t capacity = 3);
void Push(const T& data);
// 其他方法...
~Stack()
{
if (_array)
{
delete[]_array;
_capacity = _size = 0;
}
}
private:
T* _array;
int _capacity;
int _size;
};
//缺省参数不能给在函数定义,只能在声明给缺省值
//模板的作用域就是专门给一个函数或者一个类用的
//可以看{}的作用范围是那里,模板的作用范围就是哪里。
template<typename T>
Stack<T>::Stack(size_t capacity)
{
_array = new T[capacity];
_capacity = capacity;
_size = 0;
}
template<typename T>
void Stack<T>::Push(const T& data)
{
// CheckCapacity();
_array[_size] = data;
_size++;
}
関数がクラスの外で定義されている場合は、クラス テンプレートのパラメーター リストを追加する必要があります。
注: テンプレートからインスタンス化された関数の宣言と定義を分離することはお勧めできません。
注: テンプレートからインスタンス化された関数の宣言と定義を分離することはお勧めできません。
注: テンプレートからインスタンス化された関数の宣言と定義を分離することはお勧めできません。
上記の例はデモンストレーションのみを目的としています。
要約する
この記事では、関数テンプレートとクラス テンプレートに関連する問題について説明します。