【c++进阶】2、泛型编程之函数模板

来源:互联网 发布:js和jsp交互 编辑:程序博客网 时间:2024/05/17 03:08

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

输出:

int: 2
double: 2.6

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

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

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

原创粉丝点击