目录
一、模板概述
1.为什么要用模板
有一些类和函数复用时仅仅只有数据类型是不同,其代码几乎完全相同,如下图我们写一个返回和的函数。如果是int型参数调第一个,浮点型调第二个。其他类型就要再写一个相应的重载函数。为此我们可以使用一个模板来做到减少代码的复用率。
int sum(int a,int b)
{
return a+b;
}
double sum(double a,double b)
{
return a+b;
}
2.模板的形式
那么依照上述的情形,我们写一个模板。template 后加上<>,里面的T是模板参数,T的类型名可以是class或者typename。模板参数可以布置是一个。再下面跟上sum函数,这样就完成了一个类模板。这时调用sum时,编译器会根据参数类型来使用模板调相对应的函数。
template<class T>
T sum(T a,T b)
{
return a+b;
}
调用时函数参数类型与模板不匹配时,可以显示实例化,也可以由用户自己强转。
int main()
{
int a = 0;
double b = 1.1;
//隐式实例化
sum(a,(int)b);
//显示实例化
sum<int>(a,b);
return 0;
}
3、模板匹配原则
1.非模板函数可以和同名的函数模板可以同时存在;
2.如果非模板函数和同名的函数模板条件都相同,优先调用非模板函数;
3.函数模板不允许自动类型转换。
二、类模板
1.类模板形式
上述的例子为函数模板,就是模板的参数使用在函数中,同样类中也可以使用通用的模板参数来构造类模板。具体形式与函数模板相同。
template<class T>
class ListNode
{
ListNode* next;
T val;
};
类模板中的函数放在类外定义需要加模板参数列表。
ListNode<int>::ListNode(ListNode* next = nullptr,T val = 0)
{}
2.类模板实例化
类模板只能显示实例化。ListNode是类名,ListNode是类型名。
ListNode<int> ln;
三、非参数类型模板
模板可以是非参数类型,类似函数的参数,同样也可以有缺省值。
template<size_t N = 10>
应用这样的非参数模板,我们可以依据不同的需求来在类中定义不同大小的静态数组。同样地,还可以有其他的应用。
template<class T ,size_t N=10>
class A
{
T a[N];
}
四、模板的特化
使用以下这个模板类来解释模板特化。
template<class T1, class T2>
class A
{
T1 _d1;
T2 _d2;
};
1.全特化
将两个参数都进行特化。
template<>
class A<int, char>
{
int _d1;
char _d2;
};
2.偏特化
2.1部分特化
对其中一个参数特化。
template<>
class A<T1, char>
{
T1 _d1;
char _d2;
};
2.2对参数进行进一步限制
可以特化成指针或者引用。
template<>
class A<T1*, T2&>
{
T1 _d1;
T2& _d2;
};