概念:
模板是泛型编程的基础。所谓泛型编程就是编写与类型无关的逻辑代码,是一种复用的方式。模板分为模板函数和模板类。(实例化的时候才知道类型)
模板函数的书写格式如下:
**template <class 形参名1, class 形参名2, class 形参名n>(模板必须先进行声明)
返回类型 函数名(参数列表)
{
函数主体;
}
调用模板函数的过程就是实例化的过程!!!
**显示调用模板实例化: 例如 SWAP<int>(a,b); 如果不显示调用,模板和已经写好的都存在,不会调用模板函数。
**模板函数传传引用时候注意参数列表的对应。
如图下,a1,b2的引用和指针不一样,该函数的形参是引用,所以不能讲实参转换为指针类型,必须是同样类型 int [ n ] 才能使用一个模板参数,否则就匹配不到该模板函数。
非引用指针类型的,一唯数组的类型都是int*。
**关于const;const和非const都可以传给非const类型,但是非const类型不可以传给const类型;
模板类:
**模板类调用的函数才会实例化(按需实例化)
**模板类的函数最好传引用(因为模板类传参拷备一次比普通类复杂很多)
**模板类名和类型不一样;例如:类名: A 类型 A<int>
**模板的参数:class T :类型模板参数(如int、char等) size_t N: 非类型的模板参数(常量)
类模板的模板参数只能传一般的整形,浮点型、类类型不能传。
模板的模板参数:(适配器)
templete<class T,class container >或templete<class T,templete<class> class container=Vector >
模板的特化:优先会调用特化的
模板的特化是在已定义的模板基础之上,不能单独存在。
特化的分类: 1>全特化:特化全部参数
用法示例: templete <class T1 ,class T2 >
calss Data{ ……}
全特化 : templete< >
class Date<int,char>
{……}
全特化后在类外定义类成员函数不需要再声明模板,写模板参数;
2>偏特化:(半特化)
①局部特化某一个参数;
②局部特化某一个参数为某个类型;
偏特化后要写剩下的模板参数(未特化的);
用法示例:
templete <class T1 ,class T2 >
calss Data{ ……}
偏特化第二个参数为int :
templete<class T1 >
class Date<T1,int>
{……}
偏特化二个参数为指针类型 :
templete<class T1,class T2 >
class Date<T1*,T2*>
{……}
模板的类型萃取就是利用了模板的特化,来进行一部分的类型萃取调用。
模板的分离编译:
为什么模板不支持分离编译?那么该如何解决这个问题呢?
解决办法:
1. 在模板头文件 xxx.h 里面显示实例化
模板类的定义后面添加 template class SeqList<int >; 一般不推荐这种方法。
一方面老编译器可能不支持,另一方面实例化依赖调用者。(不推荐)
2. 将声明和定义放到一个文件 "xxx.hpp" 里面,推荐使用这种方法。不要分离编译
模板总结
优点:
1. 模板复用了代码,节省资源,更快的迭代开发,C++的标准模板库(STL)因此而产生。
2. 增强了代码的灵活性。
缺点:
1. 模板让代码变得凌乱复杂,不易维护,编译代码时间变长。
2. 出现模板编译错误时,错误信息非常凌乱,不易定位错误。