函数模板是模板的一种,区别于类的地方只是它修饰的是函数,而类模板修饰的是类。 函数模板出现的目的是为了让程序员可以编写和类型无关的代码。也就是说编写一个函数可以多种类型的参数通用。
注意:并不是所有的模板函数调用时都可以进行模板参数推导的 必须满足以下条件才可以: 1、模板的形参必须与模板函数的形参在位置上存在一一对应的关系 2、要推导的模板参数必须是连续且位于参数列表末尾的,这一点和给函数形参赋默认值差不多 3、编译器只根据函数调用时给出的实参列表来推导模板参数值,与函数参数类型无关的模板 参数其值无法推导。 4、与函数返回值相关的模板参数其值也无法推导。
模板函数的实例化经历两个过程: 1. 检查语法错误
主要在语法层面上进行检查,比如说少了个分号或者缺少}之类的,如果在这个过程中没有通过的话就不能进行正常编译。
2. 检查调用错误·
template <typename T> const T Max(T lhs, T rhs) { return lhs > rhs ? lhs : rhs; } class Test{} int main() { Max(1, 2); // OK Test t1, t2; Max(t1, t2); return 0; }错误信息:
严重性 代码 说明 项目 文件 行 禁止显示状态 错误 C2784 “bool std::operator >(const std::basic_string<_Elem,_Traits,_Alloc> &,const _Elem *)”:
可以看出这里并没有对类Test进行大于号‘>’重载,而在调用模板函数时传入的实参是Test类型,且在内部使用大于号进行了比较所以检查出来了错误。
这里说的重载函数只是普通的重载函数,并不包括模板函数的重载(没错,模板函数也是能重载的,除了不能提升转换,重载的条件和普通函数重载一样。)
1. 重载函数和模板函数根据参数的不同都会生成不同的函数。
#include <iostream> template<typename T1, typename T2> void maxSize(T1 num1, T2 num2){} int main() { maxSize(1, 2.0); maxSize('c', 1); return 0; system("pause"); }可以看出在内存中生成的两个maxSize()函数是占有不同的内存空间的,这一点和重载函数一模一样。
2. 所有的重载函数在编译阶段都会在内存中生成而模板函数则是什么时候调用什么时候生成。