C++函数模板的定义、使用和重载(附带实例)
所谓函数模板(function template),指的是建立一个通用函数,它所用到的数据类型(包括返回值类型、形参类型、局部变量类型)不具体指定,而是用一个虚拟类型代替(即使用一个标识符进行占位),发生函数调用时再根据传入的实参倒推出其真正类型。
函数模板是对函数功能框架的描述,不是一个实在的函数,编译器不能为其生成可执行代码。
实际开发中,通常将函数模板的定义分开写,分为模板头部分(即 template 部分)和函数名部分:
例如,定义一个求和的函数模板,计算两个数的和,代码如下:
定义函数模板后,可在程序中调用该函数模板。例如,下面的代码调用了 Sum() 函数模板:
如果采用如下形式调用 Sum() 函数模板,将会出现错误:
上述代码为 Sum() 函数模板传递了两个不同类型的参数,编译器会产生歧义。但如果调用函数模板时显式说明模板类型,就不会出现错误。例如:
用函数模板生成的实际可执行的函数称为模板函数。注意,“函数模板”与“模板函数”不是一个概念。函数模板是一个框架,它不是真正可以编译生成代码的程序;模板函数是把函数模板中的类型参数实例化后生成的函数,它和普通函数本质上是一样的,可以生成可执行代码。
与普通函数和类不同,函数模板或类模板在其他类作为友元之前必须先声明(不用定义,声明即可),否则无法通过编译。
可以定义如下函数模板:
调用 max() 即可得到两个整型数或两个浮点数中的最大值:
【实例】寻找最大值。定义函数模板 Max(),求解数组元素中的最大值。具体代码如下:
模板只作用于其下方的类或函数,所以在类外实现成员函数时要在函数前进行模板声明(即使函数没有用到该模板类型,类名里也要加上 <Type>)。
【实例】寻找最小值。先定义一个函数模板,功能是寻找两个数中的最小值;再重载该函数模板,寻找字符串中的最小值;最后在主函数中调用函数模板。具体代码如下:
函数模板是对函数功能框架的描述,不是一个实在的函数,编译器不能为其生成可执行代码。
C++函数模板的定义
函数模板的定义形式如下:
template <类型形式参数表> 返回值类型 函数名(形式参数表)
{
函数体
}
- 关键字 template 表示定义的是一个模板;
- 尖括号为该模板的类型形式参数表,不能为空,多个类型参数间用逗号隔开。
- 类型参数分为类型参数、非类型参数两种,类型参数使用关键字 class 或 typedef 开始,其后是一个用户定义的合法标识符;非类型参数与普通参数相同,通常为一个常数。
类型参数列表使用尖括号“< >”,形式参数列表使用圆括号“( )”,初学者要注意区分。
实际开发中,通常将函数模板的定义分开写,分为模板头部分(即 template 部分)和函数名部分:
template <class T> //模板头,注意这里不能有分号
void fun(T t) //定义函数模板 fun()
{
...
}
例如,定义一个求和的函数模板,计算两个数的和,代码如下:
template <class type> //模板头,type 表示待求和两个数的数据类型
Type Sum(type xvar, type yvar) //定义函数模板 Sum()
{
return xvar + yvar;
}
定义函数模板后,可在程序中调用该函数模板。例如,下面的代码调用了 Sum() 函数模板:
int iret = Sum(10,20); //调用 Sum()函数模板,计算两个整数的和 double dret = Sum(10.5,20.5); //调用 Sum()函数模板,计算两个实数的和
如果采用如下形式调用 Sum() 函数模板,将会出现错误:
int iret = Sum(10,5,20); //错误调用,传递了两个不同类型的参数 double dret = Sum(10,20.5); //错误调用,传递了两个不同类型的参数
上述代码为 Sum() 函数模板传递了两个不同类型的参数,编译器会产生歧义。但如果调用函数模板时显式说明模板类型,就不会出现错误。例如:
int iret = Sum<int>(10,5,20); //正确调用,使用<int>显式说明 double dret = Sum<double>(10,20.5); //正确调用,使用<double>显式说明
用函数模板生成的实际可执行的函数称为模板函数。注意,“函数模板”与“模板函数”不是一个概念。函数模板是一个框架,它不是真正可以编译生成代码的程序;模板函数是把函数模板中的类型参数实例化后生成的函数,它和普通函数本质上是一样的,可以生成可执行代码。
与普通函数和类不同,函数模板或类模板在其他类作为友元之前必须先声明(不用定义,声明即可),否则无法通过编译。
C++函数模板的使用
假设要通过函数求解两个数中最大的数,且这两个数的类型不确定,可能是整型数,也可能是浮点数。可以定义如下函数模板:
template <class Type> //模板头,type 表示待比较两个数的数据类型
Type max(Type a, Type b) //定义函数模板 max()
{
if(a > b)
return a;
else
return b;
}
调用 max() 即可得到两个整型数或两个浮点数中的最大值:
cout << "最大值:" << max(10,1) << endl;cout << "最大值:" << max(200.05,100.4) << endl;
【实例】寻找最大值。定义函数模板 Max(),求解数组元素中的最大值。具体代码如下:
#include <iostream>
using namespace std;
template <class type,int len> //模板头,type 表示数组类型,len 表示元素个数
Type Max(type array[len]) //定义函数模板 Max()
{
type ret = array[0]; //定义变量 ret,初始化为数组第 1 个元素的值
for(int i=1;i<len;i++) //遍历数组元素
{
ret = (ret > array[i])? ret : array[i]; //条件运算,比较相邻两个数组元素的大小
}
return ret; //返回最大值
}
int main()
{
int array[5] = {1,2,3,4,5}; //定义整型数组
int iret = Max<int,5>(array); //调用函数模板 Max(),数组类型为 int,数组元素个数为 5
cout << iret << endl;
double dset[3] = {10.5,11.2,9.8}; //定义浮点型数组
double dret = Max<double,3>(dset); //调用函数模板 Max(),数组类型为 double,数组元素个数为 3
cout << dret << endl;
}
程序运行结果为:
5
11.2
模板只作用于其下方的类或函数,所以在类外实现成员函数时要在函数前进行模板声明(即使函数没有用到该模板类型,类名里也要加上 <Type>)。
C++重载函数模板
编译器可以直接比较整型、浮点型和字符型数据,所以使用函数模板后也可以直接对这 3 种类型进行比较。但要比较字符指针指向的字符串,则需要通过重载函数模板实现(具体比较可使用库函数 strcmp())。【实例】寻找最小值。先定义一个函数模板,功能是寻找两个数中的最小值;再重载该函数模板,寻找字符串中的最小值;最后在主函数中调用函数模板。具体代码如下:
#include <iostream>
#include <string>
using namespace std;
template <class Type> //模板头,Type 表示待比较两个数的数据类型
Type mymin(Type a,Type b) //定义函数模板 mymin(),求解两个数中的最小值
{
if(a < b)
return a;
else
return b;
}
char *mymin(char *a,char *b) //重载函数模板 mymin(),求解两个字符串中的最小值
{
if(strcmp(a,b))
return b;
else
return a;
}
int main()
{
cout << "最小值:" << mymin(10,1) << endl;
cout << "最小值:" << mymin("a","b") << endl;
cout << "最小值:" << mymin("hi","mr") << endl;
}
程序运行结果为:
最小值:1
最小值:a
最小值:mr
min() 是系统函数,用户定义的函数名不能与系统函数名相同,所以这里定义为 mymin()。
ICP备案:
公安联网备案: