重载、模板、模板特例化、模板偏特例化区别
对于不同数据类型,采用不同处理 -- 重载
//交换 int 变量的值
void Swap(int *a, int *b){
int temp = *a;
*a = *b;
*b = temp;
}
//交换 float 变量的值
void Swap(float *a, float *b){
float temp = *a;
*a = *b;
*b = temp;
}
对于不同数据类型,采用统一处理 -- 模板
template<typename T> void Swap(T &a, T &b){
T temp = a;
a = b;
b = temp;
}
解决了“重载对于不同类型的复杂处理”的问题,但是存在一个问题,对于不同类型,统一处理会出问题,例如:int 类型的数据,判等可以直接用 ==,但是对于 float 类型,判等不能直接用 ==
对于不同数据类型,有统一处理,针对一些特殊类型,有特殊处理 -- 模板特例化
为了解决模板存在的问题,可以在已经有统一处理的基础上,再对特定数据类型,进行特例化:
#include <iostream>
using namespace std;
// 统一处理
template <class T>
class Compare
{
public:
bool IsEqual(const T& arg, const T& arg1);
};
// 特例处理:已经不具有template的意思了,已经明确为float了
template <>
class Compare<float>
{
public:
bool IsEqual(const float& arg, const float& arg1);
};
// 统一处理
template <class T>
bool Compare<T>::IsEqual(const T& arg, const T& arg1)
{
cout<<"Call Compare<T>::IsEqual"<<endl;
return (arg == arg1);
}
// 针对 float 类型的特例处理
bool Compare<float>::IsEqual(const float& arg, const float& arg1)
{
cout<<"Call Compare<float>::IsEqual"<<endl;
return (abs(arg - arg1) < 10e-3);
}
int main()
{
Compare<int> obj;
Compare<float> obj1;
cout<<obj.IsEqual(2, 2)<<endl;
cout<<obj1.IsEqual(2.003, 2.002)<<endl;
return 0;
}
可以看到上面对 float 处理中,所有的数据类型都特例化为 float 了,不存在任何通用类型 T,即全特例化;而偏特例化,就是即含有特定数据类型 float,也有通用数据类型 T
template <class T2>
class A<int, T2>{
...
};
函数模板是不允许偏特化的,下面的声明会编译错:
template <class T1, class T2>
void f(){}
template <class T2>
void f<int, T2>(){}
但函数允许重载,声明另一个函数模板即可替代偏特化的需要:
template <class T2>
void f(){} // 注意:这里没有"模板实参"