.初识:
C++中模板是泛型编程的基础,所谓泛型编程就是不受参数类型限制、以独立于任何特定类型的方法编写代码,使用泛型程序时,需要提供具体的所操作的类型、值。C++中的STL中的各种容器、迭代器等,都是泛型编程的实例。
模板定义:
有以下重载的函数,用以比较给定参数的大小,每一个可以比较一种参数的大小
int compare(const string &s1,const string &s2)
{
if(s1>s2)
{
return 1;
}
else if(s1<s2)
{
return -1;
}
return 0;
}
int compare(const int &n1,const int &n2)
{
if(n1>n2)
{
return 1;
}
else(n1<n2)
{
return -1;
}
return 0;
}
可以看出,重载函数的功能一样,只是参数类型不同,若想要比较其他类型,就需要一次次的重载、编写,需要提前将参数的特定类型给出。如果希望函数用于比较未知类型的数据,就不能这样编写了。
由以上的例子,引出函数模板的概念;
.函数模板:
可以不用为每个特定类型编写一个函数,而是只定义一个”函数模板“,函数模板代表了一个函数家族,在使用时被参数化,根据参数类型产生特定的类型版本,它独立于类型:
/*
compare 的模板
*/
template<typename T> //模板参数表
int compare(const T &val1,const T &val2)
{
if(val1>val2)
{
return 1;
}else if(val1<val2)
{
return -1;
}
return 0;
}
模板的定义以template开头:
template<typaneme T1,typename T2……>
函数
其中,模板参数表中的typename 可以用class 替换,二者在模板中作用一致;
模板形参T1、T2的具体类型由编译器根据所用的函数而决定,一旦编译器确定了实际的参数类型,就称它为实例化了函数模板的一个实例。且模板形参可以是表示类型的类型形参,也可以是表示常量表达式的非类型形参(后续会说到)。
函数模板的实例化:
隐式实例化:让编译器根据实参自动推导模板参数的实际类型
template<class T>
T add(const T &l,const T &r)
{
return l+r;
}
int main()
{
add(1.0,1); //该行不能通过编译,因为两个参数类型不同,编译器推导到的T的类型不同,无法确定其具体类型
//处理方式:1.将其中一个参数强转为另一个类型 2.使用显示实例化
return 0;
}
显式实例化:在调用函数时,在函数名后加<>,在其中指定模板参数的类型
int main()
{
add<int>(1.0,1);
return 0;
}
模板函数的匹配原则:
1. 一个非模板函数可以和一个同名的函数模板同时存在,而且该函数模板还可以被实例化为这个非模板函 数,如果普通函数与参数匹配,编译器直接调用,不再特化模板函数。
2. 对于非模板函数和同名函数模板,如果其他条件都相同,在调动时会优先调用非模板函数而不会从该模 板产生出一个实例。如果模板可以产生一个具有更好匹配的函数, 那么将选择模板
.模板类的声明;
template<class T>
template<class T1,class T2>
template<typename T1,typename T2>
template<typename T1,class T2>
.测试题:
1.下面有关C++中为什么用模板类的原因:
A.模板可以具有非类型参数,用于指定大小,可以根据指定的大小创建动态结构
B.模板最重要的一点就是类型无关,提高了代码复用性
C.模板运行时不检查数据类型,也不保证类型安全,相当于类型的宏替换,故错误
D.只要支持模板语法,模板的代码就是可移植的
2.在下列对fun的调用中,错误的是( )
template <class T>
T fun(T x,T y){
return x*x+y*y;
}
A.fun(1, 2) (正确,参数类型相同,不存在二义性)
B.fun(1.0, 2) (错误,参数类型不同,函数推导参数时会有二义性)
C.fun(2.0, 1.0) (正确,类型相同)
D.fun<float>(1, 2.0) (正确,通过类型实例化函数,调用正确)
3. 下列关于模板的说法正确的是( )
A.模板的实参在任何时候都可以省略 (不一定,在参数类型不同时,需要显示的指定参数类型)
B.类模板与模板类所指的是同一概念 (类模板是泛化的类,模板类是类模板的实例化)
C.类模板的参数必须是虚拟类型的 (C++中类模板的声明格式为template<模板形参表声明><类声明>,并且类模板的成员函数都是模板函数)
D.类模板中的成员函数全是模板函数 (正确)
4.下列描述错误的是( )
A.编写与类型无关的通用代码,是代码复用的一种手段。模板是泛型编程的基础
B.函数模板是一个蓝图,它本身并不是函数,是编译器用使用方式产生特定具体类型函数的模具
C.模板分为函数模板和类模板
D. 模板类跟普通类以一样的,编译器对它的处理时一样的
(编译器对模板类的处理会分别进行两次编译)