【c++】泛型编程之函数模板

1、什么是函数模板

泛型编程是为了实现代码重用,函数模板是一种常用的方法。
数据类型也可以通过参数来传递,在函数定义时可以不指明具体的数据类型,当发生函数调用时,编译器可以根据传入的参数自动确定数据类型。这就是数据类型参数化,有了数据类型参数化,可以将函数进一步抽象为函数模板。
函数模板不是一个实在的函数,编译器不能为其生成可执行代码。定义函数模板后只是一个对函数功能框架的描述,当它具体执行时,将根据传递的实际参数决定其功能。可以把函数模板理解为一种一数据类型为参数的函数定义。

2、为什么引入模板函数

在创建完成抽象操作的函数时,如:拷贝,反转和排序,你必须定义多个不同数据类型的版本以便能处理每一种数据类型。以 max() 函数为例,它返回两个参数中的较大者:

double max(double first, double second);
int max(int first, int second);
float max(float first, float second);
......

尽管这个函数针对不同的数据类型其实现都是一样的,但程序员必须为每一种数据类型定义一个单独的版本,这样不但重复劳动,容易出错,而且还带来很大的维护和调试工作量。更糟的是,即使你在程序中不使用某个版本,其代码仍然增加可执行文件的大小,大多数编译器将不会从可执行文件中删除未引用的函数。
用普通函数来实现抽象操作会迫使你定义多个函数实例,从而招致不小的维护工作和调试开销。解决办法是使用函数模板代替普通函数。

3、函数模板的定义和使用

函数模板的声明是在关键字 template 后跟随一个或多个模板在尖括弧内的参数和原型。函数模板通常被定义在头文件中,以max()函数为例:

#include 
using namespace std;

template//这里的typename可以换成class,这两个是等价的,只是后者可以使用c++中所有的标识符了
type MAX(type num1,type num2){//注意这里不要使用max作为函数名,因为c++库函数中已经有这个函数了,再次使用会命名冲突
    return (num1>num2)?num1:num2;
} 
int main(){
//以不同的数据类型来实例化函数模板
    cout<<"int:    "<1,2)<cout<<"double:    "<1.2,2.6)<

输出:

int: 2
double: 2.6

4、注意事项
①函数模板的template关键字和函数名之间不能有任何的语句,也不能有分号。
②模板函数的类型参数必须与模板定义的严格一致,若不一致将出错,因为此时自动类型转换失效(但可以实例化时手动强制类型转换为模板类型)。如:

#include 
using namespace std;

template;//错误,不能有任何语句,包括";"
type MAX(type num1,type num2){
    return (num1>num2)?num1:num2;
} 
int main(){
    cout<<"int:    "<1,2)<cout<<"double:    "<1.2,2)<//这一句将出错,因为1.2被解释为double型,而2被解释为int型,但根据模板两个参数类型应该一致,所以出错
}

③使用函数模板与使用重载函数类似,区别在于重载函数不同的重载内部可以执行不同的代码,但函数模板实例化的函数执行的代码都是一样的。

你可能感兴趣的:(C++)