引言
什么是模板
模板是泛型编程的基础,泛型编程是以一种独立于任何特定类型的方式编写代码。 模板也是创建泛型类或者函数的蓝图。 如:库容器,迭代器和算法,都是泛型编程的例子
1. 泛型编程
首先,我们应该了解什么是泛型编程?
泛型编程就好比设计一个通用的模版,使绝大部分的场景都可以通用这个模板,来解决问题等。就好比在建筑设计中,我们都需要搭建许多不同的房屋(别墅,住宅楼,办公楼),而泛型编程就好比工程师设计的建筑图纸,有了图纸才可以在许多不同的地方来建造住宅楼,而建造出来的楼层,就是通过模板实例化出来的代码段
泛型编程:编写与类型无关的通用代码,是代码复用的一种手段。模板是泛型编程的基础。
如下场景
cpp
void Swap(int& left, int& right)
{
int temp = left;
left = right;
right = temp;
}
void Swap(double& left, double& right)
{
double temp = left;
left = right;
right = temp;
}
void Swap(char& left, char& right)
{
char temp = left;
left = right;
right = temp;
}
//......
使用函数重载固然也可以解决同样的问题,但这样也会带来一些问题:
- 重载的函数仅仅是类型不同,当有新类型的出现,有需要重新设计重载函数
- 代码的可维护性低,一个出错可能所有重载都出错

2. 函数模板
2.1 概念:通过使用类型参数来实现一个函数家族,使用时被参数化,根据参数类型产生相应的函数类型模板
2.2 模板格式:
注意需要几个不同类型的参数就typename 几个参数模板, 关键字 "typename" 是标注当前为 数据类型 [有时可能编译器会出现某个名字是变量还是类型会产生分歧]
template<typename T,typename K,>
返回值类型 函数名 (参数列表 (T ,K)){}
cpp
template<typename T>
void Swap( T& left, T& right)
{
T temp = left;
left = right;
right = temp;
}//也可以用指针 T*
2.3 函数模板的原理
函数模板是一个蓝图,它本身并不是函数,是编译器用使用方式产生特定具体类型函数的模具。所以其实模板就是将本来应该我们做的重复的事情交给了编译器。
也就是说在没有套用模板的时候,编译器是不会运行这段代码的

2.4 函数模板的实例化
用不同类型的参数 使用函数模板 ,称为函数模板的实例化。而模板实例化分为:隐式实例化 和显式实例化
隐式实例化:
cpp
template<class T>
T add(const T& i,const T j)
{
return i+j;
}
int main()
{
int i = 5,j = 4;
double b = 5.1, d = 6.2;
add(i,j);
add(b,d);
return 0;
}
显式实例化
如上的add函数
cpp
void test()
{
int a= 10;
double b= 2.1;
add<int>(a, b) //b会强制类型转换为int
}
2.5 模板餐宿的匹配原则
- 一个非模板函数可以和一个同名的函数模板同时存在,而且该函数模板还可以被实例化为这个非模板函
数
cpp
// 专门处理int的加法函数
int Add(int left, int right)
{
return left + right;
}
template<class T>
T add(const T& i,const T j)
{
return i+j;
}
void test()
{
Add(1, 2); // 与非模板函数匹配,编译器不需要特化
Add<int>(1, 2); // 调用编译器特化的Add版本
}
在这种情况下会优先匹配有实例化的函数,当没有此类型的实例化函数才会调用模板
对于非模板函数和同名函数模板,如果其他条件都相同,在调动时会优先调用非模板函数而不会从该模板产生出一个实例。如果模板可以产生一个具有更好匹配的函数, 那么将选择模板
模板函数不允许自动类型转换,但普通函数可以进行自动类型转换
3. 类模板
3.1 类模板的定义,具体可参考vector的实现
cpp
template<class T1, class T2, ..., class Tn>
class 类模板名
{
// 类内成员定义
};
3.2 类模板的实例化
类模板实例化与函数模板实例化不同,类模板实例化需要在类模板名字后跟<>,然后将实例化的类型放在<>中即可,类模板名字不是真正的类,而实例化的结果才是真正的类
cpp
// Vector类名,Vector<int>才是类型
Vector<int> s1;
Vector<double> s2;