void Swap(int & x, int & y) { int tmp = x; x = y; y = tmp; }
void Swap (double & xr double & y) { double tmp = x; x = y; y = tmp; }
template <class 类型参数1, class类型参数2, ...>
返回值类型 模板名(形参表)
{
函数体
}
template <typename 类型参数1, typename 类型参数2, ...>
函数模板看上去就像一个函数。前面提到的 Swap 模板的写法如下:template <class T> void Swap(T & x, T & y) { T tmp = x; x = y; y = tmp; }T 是类型参数,代表类型。编译器由模板自动生成函数时,会用具体的类型名对模板中所有的类型参数进行替换,其他部分则原封不动地保留。同一个类型参数只能替换为同一种类型。编译器在编译到调用函数模板的语句时,会根据实参的类型判断该如何替换模板中的类型参数。
#include <iostream> using namespace std; template<class T> void Swap(T & x, T & y) { T tmp = x; x = y; y = tmp; } int main() { int n = 1, m = 2; Swap(n, m); //编译器自动生成 void Swap (int &, int &)函数 double f = 1.2, g = 2.3; Swap(f, g); //编译器自动生成 void Swap (double &, double &)函数 return 0; }编译器在编译到
Swap(n, m);
时找不到函数 Swap 的定义,但是发现实参 n、m 都是 int 类型的,用 int 类型替换 Swap 模板中的 T 能得到下面的函数:
void Swap (int & x, int & y) { int tmp = x; x = y; y = tmp; }该函数可以匹配
Swap(n, m);
这条语句。于是编译器就自动用 int 替换 Swap 模板中的 T,生成上面的 Swap 函数,将该 Swap 函数的源代码加入程序中一起编译,并且将Swap(n, m);
编译成对自动生成的 Swap 函数的调用。Swap(f, g);
时会用 double 替换 Swap 模板中的 T,自动生成以下 Swap 函数:
void Swap(double & x, double & y) { double tmp = x; x = y; y = tmp; }然后再将
Swap(f, g);
编译成对该 Swap 函数的调用。模板名<实际类型参数1, 实际类型参数2, ...>
的方式告诉编译器应该如何实例化模板函数。例如下面的程序:#include <iostream> using namespace std; template <class T> T Inc(int n) { return 1 + n; } int main() { cout << Inc<double>(4) / 2; return 0; }
Inc<double>(4)
指明了此处实例化的模板函数原型应为:
double Inc(double);
编译器不会因为实参 4 是 int 类型,就生成原型为 int Inc(int) 的函数。因此,上面程序输出的结果是 2.5 而非 2。template <class Tl, class T2> T2 print(T1 argl, T2 arg2) { cout << arg1 << " " << arg2 << endl; return arg2; }
#include <iostream> using namespace std; template <class T> T MaxElement(T a[], int size) //size是数组元素个数 { T tmpMax = a[0]; for (int i = 1; i < size; ++i) if (tmpMax < a[i]) tmpMax = a[i]; return tmpMax; } class CFraction //分数类 { int numerator; //分子 int denominator; //分母 public: CFraction(int n, int d) :numerator(n), denominator(d) { }; bool operator <(const CFraction & f) const {//为避免除法产生的浮点误差,用乘法判断两个分数的大小关系 if (denominator * f.denominator > 0) return numerator * f.denominator < denominator * f.numerator; else return numerator * f.denominator > denominator * f.numerator; } bool operator == (const CFraction & f) const {//为避免除法产生的浮点误差,用乘法判断两个分数是否相等 return numerator * f.denominator == denominator * f.numerator; } friend ostream & operator <<(ostream & o, const CFraction & f); }; ostream & operator <<(ostream & o, const CFraction & f) {//重载 << 使得分数对象可以通过cout输出 o << f.numerator << "/" << f.denominator; //输出"分子/分母" 形式 return o; } int main() { int a[5] = { 1,5,2,3,4 }; CFraction f[4] = { CFraction(8,6),CFraction(-8,4), CFraction(3,2), CFraction(5,6) }; cout << MaxElement(a, 5) << endl; cout << MaxElement(f, 4) << endl; return 0; }编译到第 41 行时,根据实参 a 的类型,编译器通过 MaxElement 模板自动生成了一个 MaxElement 函数,原型为:
int MaxElement(int a[], int size);
编译到第 42 行时,根据 f 的类型,编译器又生成一个 MaxElement 函数,原型为:CFraction MaxElement(CFraction a[], int size);
在该函数中,用到了<
比较两个 CFraction 对象的大小。如果没有对<
进行适当的重载,编译时就会出错。Copyright © 广州京杭网络科技有限公司 2005-2025 版权所有 粤ICP备16019765号
广州京杭网络科技有限公司 版权所有