目录
前言
泛型编程:用一个标志来表示类型,不是实际的类型。独立于任何特定类型的编程,c++的一个部分。
一、函数模板是什么?
函数模板只是声明了一个函数的描述即模板,不是一个可以直接执行的函数,只有根据实际情况用实参的数据类型代替类型参数标识符之后,才能产生真正的函数。 关键字typename也可以使用关键字class,这时数据类型参数标识符就可以使用所有的C++数据类型。
二、函数模板的注意事项
1.函数模板的格式
template<class T1,typename T2>
返回值 函数名(参数){ }
template ----- 声明创建模板。
typename ----- (也可以用class代替)表明后的类型是一个通用类型,或许叫做虚拟类型。
T1,T2--------- 通用类型或者虚拟类型,可以在函数中直接当做普通类型使用。
代码如下(示例):
2.函数模板的使用
第一种: 函数名 <实际类型1,实际类型2>(参数列表)
显式类型推导 add<int>(1,2)
第二种: 函数名(参数)
隐形类型推导 add(1,2)
注意:显示类型推导 参数和推导的类型必须一致。
如果有普通函数和模板函数,在调用时可以用显示调用,省略类型的方式 add<>(1,2)。
代码如下(示例):
3.函数模板的重载
和普通函数的重载相似,也是同一个作用域类函数名相同参数列表不同。
以下是参数顺序不同的重载:
template <class T1,class T2>void add(T2 a,T1 b)
template <class T1,class T2>void add(T1 a,T2 b)
注意,在函数参数顺序不同的重载中,实例化的时候不可以是相同类型。
例如 swap1<int ,int >(1,2)则没法匹配哪个函数。
以下是参数个数不同的重载:
template <class T1,class T2> void add(T1 a,T2 b)
template <typename T2> void add(T2 t)
传入不同的参数,调用不同的版本。
代码如下(示例):
4.函数模板的特化
定义:为了解决函数模板的局限性,在定义函数模板时候,直接确定好T的类型。也就是特定的类型模板。
格式: template<class T> 返回值 函数名(类名& 对象){ }
匹配:如果传入的是自定义类型,并且和特化版本匹配,会优先使用特化版本
注意:如果特化后,类型确定才可以使用自定义类型中的成员变量和方法。
5.多文件实现函数模板
在定义函数或者类的时候,.h文件和.cpp文件,定义和申明分开。
出现连接错误的原因:函数模板是在调用时确定的版本,而调用时.h中没有函数实现,出现连接错误,找不到函数体。
如果分开后,编译会出现连接错误。
第一种办法:在main中#include <xxx.h> 和 #include <xx.cpp>
第二种办法:模板的定义和申明都放在.h头文件中。
6.函数模板的嵌套
定义:在函数模板中调用另外一个函数模板
代码如下(示例):
7.函数模板的非类型参数
希望传入函数一个特定的确定参数,但不希望放在小括号中。
可以通过非类型参数实现。在模板<>中加了一个参数,但这个参数不是类型参数,是具体的某一个值。
格式:template<class T,基本数据类型 变量名>
返回值 函数名(T& 变量)
例如:template <class T,int size>
void px(T* a);
注意:在上例子中,size是通过模板传入到函数中,可以当做普通变量使用
非类型参数都是常量,在函数中不允许修改,只可以使用,定义非类型参数变量时候,需 要加const。
代码如下(示例):
8.函数模板和普通函数的区别
函数只可以有一种数据类型相匹配,模板有多种类型。
隐式推导优先使用普通函数,只有普通函数不匹配才使用函数模板。
函数模板只有在调用时,才会构建函数,而普通函数是在编译时。
普通函数调用时候可以发生自动类型转换,而函数模板不行。
总结
函数模板克服了C语言解决类似问题时使用大量不通函数名表示相关功能。克服了宏定义不能进行参数类型检查的弊端。克服了C++函数重载用相应函数名字重写几个函数的繁琐。
以上就是今天要讲的内容,本文仅仅简单介绍了函数模板的使用,而函数模板提供了大量能使我们快速便捷地处理数据的函数和方法,提高了我们编程的效率。