1、模板的概念
模板是泛型编程的基础,所谓泛型编程就是编写与类型无关的逻辑代码。提高了编写代码的效率,使代码能够复用。
2、模板的分类
模板函数、模板类
3、模板的格式
template<class 形参名1,class 形参名2>
注释:template是关键字,“模板”的意思,class代表类型,也可以用typename表示,形参名大多用T来表示。模
板的参数可以是非类型的,例如在写静态顺序表时便可以用非类型的模板参数来指定容量的大小;(template<
size_t Capacity>);
*注意:浮点数和类对象(自定义类型)是不允许作为非类型的模板参数
4、模板的用法
下面用一个例子来说明模板的用法:
#include
using namespace std;
template
T Add(const T& a,const T& b)
{
return a+b;
}
int main()
{
cout<
<
在上面的代码中Add()函数是模板函数;以前我们实现这种函数时往往因为参数类型的不同要写好几个函数,但有了
模板之后写一个模板函数就可以了。那编译器是如何做到的呢?
1)编译器首先根据template确定此函数(类)是模板函数(类);
2)编译器推演:编译器调用模板函数时,编译器会根据传递的参数自动推演出模板形参的类型T;
3)模板函数的实例化:根据推演出的类型,实例化出代码;模板类一般都是直接显示实例化,即直接给出类型;
***5、模板的分离编译**
模板是不支持分离编译的,下面举一个例子
![](https://img-blog.csdn.net/20170927132908458?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzgxMTc0Nzg=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
以前在c语言阶段,我们在写一个工程时通常是将函数的声明和定义分开写的;但通过上面的例子,我们可以知道模
板是不支持分离编译的;而且可以看出上面的执行结果,出现了一个链接错误,说明程序在链接时候出了问题。那么
程序是如何编译的?
说明:在编译时,是以单元进行编译的,即一个编译单元(translation unit)是指一个.cpp文件以及它所#include
的所有.h文件,.h文件里的代码将会被扩展到包含它的.cpp文件里。
![](https://img-blog.csdn.net/20170927132937762?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzgxMTc0Nzg=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
分析:在预处理时将template.h;分别展开在test.cpp和template.cpp中;在编译期间生成代码;但在template.i中并
没有实例化出代码,因为编译器不知道T的类型;经过汇编分别生成两个.o文件;在链接前,各个.cpp文件都是独立
编译,互相不可见的,在连接时找到main()函数,找Add()函数的地址,template.o并没有实例化出代码,所以找不
到Add()函数的地址,因此在链接时Add是无法解析的外部符号。
解决方案:
1. 在模板头文件 xxx.h 里面显示实例化->模板类的定义后面添加 template class 函数名<int >(一般不推荐这种方
法编译器可能不支持,另一方面实例化依赖调用者);
2. 将声明和定义放到一个文件里面(常用)
6.模板的总结
优点:
1. 模板复用了代码,节省资源,更快的迭代开发,C++的标准模板库(STL)因此而产生。
2. 增强了代码的灵活性。
缺点:
1. 模板让代码变得凌乱复杂,不易维护,编译代码时间变长。
2. 出现模板编译错误时,错误信息非常凌乱,不易定位错误。