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号
广州松河信息科技有限公司 版权所有