在 C++ 中,模板分为函数模板和类模板两种。函数模板是用于生成函数的,类模板则是用于生成类的。
一、函数模板
- 函数模板
写法:
template<class 类型参数1,class 类型参数2,...>
//class 可用typename 替换
返回值类型 模板名(形参表)
{
函数体;
}
1.编译
1、定义点 模板头部
2、调用点 模板函数
2.模板的实例化
编译器由模板自动生成函数的过程叫模板的实例化。
#include<iostream>
using namespace std;
template<class T>
void Swap(T &x,T &y)
{
T tmp=x;
x=y;
y=tmp;
}
int main()
{
int n=1,m=2;
Swap(n,m); //编译器自动生成void Swap(int &,int &)
double f=1.2,g=2.3;
Swap(f,g);//编译器自动生成void Swap(double &,double &)
return 0;
}
T 是类型参数,代表类型。编译器由模板自动生成函数时,会用具体的类型名对模板中所有的类型参数进行替换,其他部分则原封不动地保留。同一个类型参数只能替换为同一种类型。编译器在编译到调用函数模板的语句时,会根据实参的类型判断该如何替换模板中的类型参数。
3.模板函数
由模板实例化得到的函数称为模板函数。
编译器对模板进行实例化时,并非只能通过模板调用语句的实参来实例化模板中的类型参数,模板调用语句可以明确指明要把类型参数实例化为那种类型。
写法:
模板名<实际类型参数1,实际类型参数2,...>
例:
#include<iostream>
using namespace std;
template <class T>
T fun(int n)
{
return 1+n;
}
int main()
{
cout<<fun<double>(4)/2;//指明此处实例化的模板原型为double fun(double)
return 0;
}
4.模板的实参推演
注意:
- 不能产生二义性
- 有实参
5.模板的特例化(专用化)
模板不能满足特殊类型的需求
特例化的调用优先级>模板实例化版本
特例化应该符合模板的实例化逻辑
- 完全特例化(全特化) 具体到某一个类型
- 部分特例化(偏特化) 具体到一部分类型
6.模板类型参数列表
1、类型参数
template<class T> class A // T是类型模板参数,常见的。
{
T m_a;
};
2、非类型参数
template<int val> class B // int val是非类型模板参数,不常见的。一般用于指定常数。参见下面的用法。
{
int m_b[val];
}
7.模板的默认值
函数模板的默认值 不是C++98 C++11
优先使用实参推演
如果有实参推演,则不适用默认值,反之则使用
不遵循自右向左一次赋值的规则
9.模板接收不明确类型的返回值
10.模板的重载
1、普通函数版本
2、模板版本
3、模板特例化版本
1>3>2 精确匹配
11.模板的显示实例化
模板一般在.h文件中实现