如果给出任意两个数,让他们完成相加求和的操作。我们应该怎么做呢?
在C语言的学习过程中,如果我们遇到此类题型,按照所学的C语言的知识,我们会给出以下3种解决方法:泛型、函数重载、宏函数。
但这三种解决问题的方法,却存在着极大的缺点。泛型它是个半闭半开区间,容易发生越界问题,而函数重载与宏函数则是处理类型较少。显然这三种方法,不足以解决这种问题的多样性。
C+++的函数模板却可以完美的解决此类问题。
模板的定义
template<typename T..>
T 函数名(T 形参,T 形参..)
{
函数体
}
typename的作用:(1)定义模板类型参数(2)T声明模板中的类型
可以使用任何类型来实例化该类型参数,只要所用类型提供模板使用的操作就可以。
模板的使用
通常而言,并不是把模板编译成一个可以处理任何类型的单一实体;而是对于实例化模板参数的每种类型,都从模板产生一个不同的实体。这种用具体类型代替模板参数的过程叫做实例化,它产生了一个模板的实例。
因此模板其实编译了两次分别是
(1)实例化之前,先检查模板本身语法是否正确
(2)实例化的时候,看模板代码是否所有的调用都有效。
模板的实例化
函数模板———实例化———>模板函数
显式实例化
当模板参数和调用参数没有发生关联,或者不能由调用参数来决定模板参数的时候,在调用时就必须显式指定模板实参。切记,模板实参演绎并不适合返回类型。
例如:
template< typename T,typename R,typename Q>
Q Sum(T a,T b)
{
return a+b;
}
这样就必须显示实例化
Sum<int ,double ,double>(2,3.1); //如果不写成这样,编译器是无法参演出返回值的类型
模板的特例化(自定义)
注意:与函数模板的修饰要一致
模板的头部编译
如果不给出类型,模板将进行实参推演
注意:不能让编译器产生二义性、不能缺少实参(要有推演依据)
模板参数
函数模板有两种类型参数
(1)模板参数:位于函数模板名称前,在尖括号中声明
template< typename T> //T是模板参数
(2)调用参数:位于函数模板之后,在圆括号中声明
T 函数名(T a,T b)//a,b是调用参数
模板的非类型参数 : 模板的非类型形参也就是内置类型形参,如template< typename T, int a>其中int a就是非类型的模板形参。
非类型形参在模板定义的内部是常量值,也就是说非类型形参在模板的内部是常量。
非类型模板的形参只能是整型,指针和引用,像double,float, String **这样的类型是不允许的。但是double &,double *,对象的引用或指针是正确的。
如果要接受一个不明确类型 用 auto:自动适应调节类型
模板的默认值 在C++98中不支持,但C++11中可以支持
模板的重载
对于非模板函数和同名的函数模板,如果其他条件都是相同的话,那么在调用的时候,重载解析过程通常会优先调用非模板函数,而不会从该模板产生出一个实例。所以其优先级为 普通函数版本>模板特例化版本>模板版本