1.概念:
就是告诉编译器一个模子,让编译器根据不同的类型利用该模子来生成代码;
模板分为函数模板和类模板。
2.函数模板
1.概念:函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本;
语法格式:template<typename T1, typename T2,…,typename Tn>
返回值类型 函数名(参数列表){}
template<typename T>
T add(const T& left,const T& right)
{
return left+right;
}
//注意:typename是用来定义模板参数关键字,也可以使用class
函数模板并不是真正的函数,而是编译器生成具体类型Add函数的模具;
2.函数模板的实例化
用不同类型的参数使用函数模板时,称为函数模板的实例化。模板参数实例化分为:隐式实例化和显式实例化。
隐式实例化:让编译器根据实参推演模板参数的实际类型
template<class T>
T Add(const T& left, const T& right)
{
return left + right;
}
int main()
{
int a1 = 10, a2 = 20;
double d1 = 10.0, d2 = 20.0;
Add(a1, a2);
//实参推演类型int,int,所以T就是int
Add(d1, d2);
//实参推演类型double、double,所以T就是double
Add(a1,d2);
//实参推演类型int、double,T不知应该是什么类型,所以会编译失败
}
显式实例化:在函数名后的<>中指定模板参数的实际类型。
int main(void)
{
int a = 10;
double b = 20.0;
Add<int>(a, b);
// 显式实例化,生成int类型代码
return 0;
}
3.类模板
1.概念
类模板,模板的类型参数由关键字class 或关键字typename 及其后的标识符构成。在模板参数表中关键字class 和typename 的意义相同。
类模板一般形式:
template <class 参数名1,class 参数名2,…>
class 类名
{
类声明体
};
2.类模板的特化
全特化:将模板参数列表中所有的参数都确定化。
template<class T1, class T2>
class Data
{
public:
Data()
{
cout << "Data<T1, T2>" << endl;
}
private:
T1 _d1;
T2 _d2; };
template<>
class Data<int, char>
{
public:
Data()
{
cout << "Data<int, char>" << endl;
}
private:
T1 _d1;
T2 _d2;
};
void TestVector()
{
Data<int, int> d1;
Data<int, char> d2;
}
偏特化:任何针对模版参数进一步进行条件限制设计的特化版本
对于以下模板类:
template<class T1, class T2>
class Data
{
public:
Data() {cout<<"Data<T1, T2>" <<endl;}
private:
T1 _d1;
T2 _d2;
}
a.部分特化:将模板参数类表中的一部分参数特化
template <class T1>
class Data<T1, int>
{
public:
Data() {cout<<"Data<T1, int>" <<endl;}
private:
T1 _d1;
int _d2;
}
b.参数更进一步的限制
//两个参数偏特化为指针类型
template <typename T1, typename T2>
class Data <T1*, T2*>
{
public:
Data() {cout<<"Data<T1*, T2*>" <<endl;}
private:
T1 _d1;
T2 _d2;
}
//两个参数偏特化为引用类型
template <typename T1, typename T2>
class Data <T1&, T2&>
{
public:
Data(const T1& d1, const T2& d2)
: _d1(d1)
, _d2(d2)
{
cout<<"Data<T1&, T2&>" <<endl;
}
private:
const T1 & _d1;
const T2 & _d2;
};
void test2 ()
{
Data<double , int> d1; // 调用特化的int版本
Data<int , double> d2; // 调用基础的模板
Data<int *, int*> d3; // 调用特化的指针版本
Data<int&, int&> d4(1, 2); // 调用特化的指针版本
}