函数模版
函数模版的概念:函数模版代表了一个函数家族,该函数模版与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型模版。
函数模版格式:template<typename T1, typename T2,……>
返回值类型 函数名 参数列表{}
template<class T>
void Swap(T& a,T& b)
{
T tmp = a;
a = b;
b = tmp;
}
注意⚠️:typename是用来定义模版参数的关键字,也可以使用class(切记:不能使用struct代替class)
函数模版的实例化
用不同类型的参数使用函数模版时,称为函数模版的实例化。模版参数实例化分为:隐式实例化和现实实例化
隐式实例化:让编译器根据实参来推演模版参数的实际类型
template<class T>
void Swap(T& a,T& b)
{
T tmp = a;
a = b;
b = tmp;
}
int main()
{
int a = 3;
int b = 4;
float c = 1.1;
float d = 2.2;
Swap(a, b);
Swap(a, c);
return 0;
}
上述程序无法通过编译,因为a、c不是同一个类型,对于此种问题,我们有两种解决方案:1、用户自己来使用强制类型转换,swap(a,(int)b)
2、使用显示实例化
显示实例化:
在函数名后的<>中指定模版参数的实际类型
template<class T>
void Swap(T& a,T& b)
{
T tmp = a;
a = b;
b = tmp;
}
int main()
{
int a = 3;
int b = 4;
float c = 1.1;
float d = 2.2;
Swap<int>(a, b);
return 0;
}
模版参数的匹配原则:
1、一个非模版函数可以和一个同名的函数模版同时存在,而且该函数模版还可以被实例化为这个非模版函数
//专门处理int型的函数
int Add(int left ,int right)
{
return left+right;
}
//通用加法函数
template<class T>
T Add(T left, T right)
{
return left+right;
}
void Test()
{
Add(1,2);//调用非模版函数,不需要编译器特化
Add<int>(1,2);//调用编译器特化的add版本
}
对于非模版函数和同名函数模版,如果其他条件相同,在调用时会优先调用非模版函数而不会从该函数模版中产生一个实例。如果模版可以产生一个更匹配的函数,那么将选用此模版。
//专门处理int型的函数
int Add(int left ,int right)
{
return left+right;
}
//通用加法函数
template<class T>
T Add(T left, T right)
{
return left+right;
}
void Test()
{
Add(1,2);//调用非模版函数,不需要编译器特化
Add<int>(1,2.0);//模版函数可以产生更匹配的函数,调用编译器特化的add版本
}
模版函数不允许自动类型转化,但普通函数可以进行自动类型转化
类模版
类模版的定义格式:
template<class T>
class Test
{
};
类模版的实例化:
类模版实例化需要在类模版后<>,然后将实例化的类型放在<>中即可,类模版名字不是真正的类,而实例化的结果才是真正的类。