1.多参数类模板
类模板可以定义任意多个不同的类型参数:
函数模板也可以支持多个不同类型参数。
使用类模板必须一一指定类型,函数模板可以不用。
2.类模板可以被特化
指定类模板的特定实现。
部分类型参数必须显示指定。
根据类型参数分开实现类模板。
特殊化为只接受一个类型(T1和T2类型相同)。在指定实际类型时,如果T1和T2类型相同,编译器会优先使用右边的模板。编译器会根据实际情况分析使用左边或者右边。编译器认为这两个模板是同一个,在使用的时候会根据参数进行选择使用。
部分特化 :用特定规则约束类型参数。
代码示例:第一种方式部分特化
template<typename T1>
class example<T1, char> //这里指定第二个模板参数为char
{
public:
example();
~example();
private:
T1 data1;
char data2;
int data3;
};
template<typename T1> //由于只指定了第二个模板参数的类型,所以这里还有给出模板形参T1
example<T1, char>::example()
:data1(3),
data2(3),
data3(3)
{
cout << "偏特化<T1, char>实例构造完成" <<endl;
}
template<typename T1>
example<T1, char>::~example()
{
cout << "偏特化<T1, char>实例析构完成" <<endl;
}
代码示例:第二种方式部分特化
template<typename T1, typename T2>
class example<T1 *, T2 *> //这里特化为两模板参数为指针版本
{ //当实例化对象时,若指定的模板参数为两指针,则会通过此来进行实例化
public:
example();
~example();
private:
T1 data1; //对于data1和data2而言,它们只关心实例化时传入指针解引用后的类型
T2 data2;
int data3;
T1 * data4; //对于data4和data5而言,它们关心实例化时传入的指针
T2 * data5;
};
template<typename T1, typename T2> //对于编译器而言
//模板的类型仍是未知的,所以需要给出T1、T2两个模板参数
example<T1 *, T2 *>::example()
:data1(0),
data2(0),
data3(0),
data4(&data1),
data5(&data2)
{
cout << "构造<T1 *, T2 *>" << endl;
}
template<typename T1, typename T2>
example<T1 *, T2 *>::~example()
{
cout << "析构<T1 *, T2 *>" << endl;
}
完全特化 :完全显示指定类型参数。
代码示例:
template<> //C++语法规定,此处加template<>是为了说明正在定义一个特例化版本
class example<int, char> //此处尖括号内的内容说明模板参数为int、char
{
public:
example();
~example();
private:
int data1;
char data2;
int data3;
};
//由于已经指定了模板参数,所以这里不用给出模板形参
example<int, char>::example()
:data1(2),
data2(2),
data3(2)
{
cout << "构造完成全特化<int, char>的类模板实例" << endl;
}
example<int, char>::~example()
{
cout << "析构完成全特化<int, char>的类模板实例" << endl;
}
3.特化的深入理解
代码示例:函数模板特化
#include <iostream>
#include <string>
using namespace std;
template
< typename T >
bool Equal(T a, T b) //函数模板
{
cout << "bool Equal(T a, T b)" << endl;
return a == b; //不能用来比较两个浮点数相等。解决办法:函数模板特化
}
template //函数模板完全特化——显示声明
< >
bool Equal<double>(double a, double b) //浮点数精度不够。完全特化
{
const double delta = 0.00000000000001;
double r = a - b;
cout << "bool Equal<double>(double a, double b)" << endl;
return (-delta < r) && (r < delta); //用这种方式判断两个数相等
}
int main()
{
cout << Equal( 1, 1 ) << endl; //函数模板
cout << Equal<double>( 0.001, 0.001 ) << endl;
return 0;
}
结果:
bool Equal(T a, T b)
1
bool Equal<double>(double a, double b)
1
定义重载函数:
#include <iostream>
#include <string>
using namespace std;
template
< typename T >
bool Equal(T a, T b) //函数模板
{
cout << "bool Equal(T a, T b)" << endl;
return a == b; //不能用来比较两个浮点数相等。解决办法:函数模板特化
}
template //函数模板完全特化——显示声明
< >
bool Equal<double>(double a, double b) //浮点数精度不够。完全特化
{
const double delta = 0.00000000000001;
double r = a - b;
cout << "bool Equal<double>(double a, double b)" << endl;
return (-delta < r) && (r < delta); //用这种方式判断两个数相等
}
bool Equal(double a, double b) //函数
{
const double delta = 0.00000000000001;
double r = a - b;
cout << "bool Equal(double a, double b)" << endl;
return (-delta < r) && (r < delta);
}
int main()
{
cout << Equal( 1, 1 ) << endl; //函数模板
cout << Equal( 0.001, 0.001 ) << endl;
return 0;
}
结果:
bool Equal(T a, T b)
1
bool Equal(double a, double b)
1
分析:
同名的特化函数和重载函数,会优先使用重载函数。
代码示例:如果一定要使用特化函数,要加上加上<>。
int main()
{
cout << Equal( 1, 1 ) << endl; //函数模板
cout << Equal<>( 0.001, 0.001 ) << endl; //加上<>,让编译器先匹配特化
return 0;
}
结果:
bool Equal(T a, T b)
1
bool Equal<double>(double a, double b)
1
4.工程中的建议(编码原则)
-> 当需要重载函数模板时,优先考虑实验模板特化;
-> 当模板特化无法满足需求,再使用函数重载!
小结:
-> 类模板可以定义任意多个不同的类型参数。
-> 类模板可以被部分特化和完全特化。
-> 特化的本质是模板的分开实现。
-> 函数模板只支持完全特化。