首页 > 编程笔记 > C++笔记 阅读:61

C++函数模板的定义、使用和重载(附带实例)

所谓函数模板(function template),指的是建立一个通用函数,它所用到的数据类型(包括返回值类型、形参类型、局部变量类型)不具体指定,而是用一个虚拟类型代替(即使用一个标识符进行占位),发生函数调用时再根据传入的实参倒推出其真正类型。

函数模板是对函数功能框架的描述,不是一个实在的函数,编译器不能为其生成可执行代码。

C++函数模板的定义

函数模板的定义形式如下:
template <类型形式参数表> 返回值类型 函数名(形式参数表)
{
    函数体
}

类型参数列表使用尖括号“< >”,形式参数列表使用圆括号“( )”,初学者要注意区分。


实际开发中,通常将函数模板的定义分开写,分为模板头部分(即 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

程序中定义了一个函数模板 Max(),用来求解数组中最大的元素值。其中,模板参数使用了模板类型参数 type(表示数组类型)和模板非类型参数 len(表示元素个数)。给定数组元素后,程序将输出数组中的最大值。

模板只作用于其下方的类或函数,所以在类外实现成员函数时要在函数前进行模板声明(即使函数没有用到该模板类型,类名里也要加上 <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

程序在重载函数模板 mymin() 时,使用 strcmp() 库函数完成字符串的比较。最终,通过 mymin() 函数可获取整型、浮点型、字符型以及字符串数据中的最小值。

min() 是系统函数,用户定义的函数名不能与系统函数名相同,所以这里定义为 mymin()。

相关文章