函数模板
template < areaA >
H functionname (T,G…){
body
}
- areaA中的参数必须被确定,如果函数中没用到其中的某一个,那么编译器推到不出来,将匹配不上,从而报错。
- 函数模板可以重载,可以重载为函数,或者另外的函数模板。
- functionname< type >(a,b) 主函数使用的时候可以使用这种方式,对type进行赋类型,从而达到显示匹配
- 根据3的显示匹配,上面的模板函数中有没有使用areaA的地方,但是在使用模板的时候在<>内对那么没有确定的地方进行赋类型,也不会报错。
- 重载函数的时候,优先匹配重载函数,其次模板
- 下面这个不行,因为出现了二义性
template <typename T>
void ss(T,T){
int i;
int g = i;
return;
}
template <typename T>
void ss(T,int){
int i;
int g = i;
return;
}
int main(){
ss(i, i + 1);
return 0;
}
- 模板非类型参数:则形参的类型是某种具体的数据类型。
模板非类型参数表示该参数名代表了一个潜在的值,而该值代表了模板定义中的一个常量。
模板非类型参数被用作一个常量值出现在模板定义的余下部分。
它可以用在要求常量的地方,如 数组声明中指定数组的大小或作为枚举常量的初始值.
template <class T, int i>
int find(T a[],T k)
{
for(int j=0;j<i;j++)
if(a[j]==k)
return(j);
return(-1);
}
void main(){
int a[10]={0};
cout<<find<int,10>(a,1);
}
类模板
template < areaA >
*classname{
body
}
上面这个是主模板。
- 类模板在函数中不能进行隐式实例化,必须声明class< type > a
- 因为每个类模板的实例化表示截然不同的类,所以每个类都有自己的static成员。
- 在类中同样有模板非类型参数,如果在类模板中areaA中有int i的话,在主函数中class<…10> a和class<…12> b a和b是两个截然不同的类
- 类模板也允许默认参数
template
class Stack{}
main:
Stack<> object;
5.定制类
template<>// 这里不同写参数
class List<double> {//这里是以什么类型来定制的类
public:
void Set(double);
double Get();
void print();
private:
double i;
int m;
};//一个普通类
void List<double>::Set(double k){i = k+1;}
double List<double>::Get(){return(-1*i);}
void List<double>::print()
{cout<<i<<endl;}
//普通的函数
main:
void main(){
List<int> i;
i.Set(1);
cout<<i.Get()<<endl;
List<double> k;
k.Set(1);
cout<<k.Get()<<endl;
k.print();
}
- 局部定做:
template <typename T1,typename T2>
class A//主模板
{};
template <typename T>
class A<T,T>{}; //仍为类模板,由于主模板有两个参数,所以这里<>中的元素也要为二
// <>中第一个T代替class中T1的位置,第二个T代替T2的位置
template <typename T>
class A<T,Cat> // CAT代替T2的位置...
{};
main:
A<int,Cat> aa1;
A<int,int> aa2;
A<Cat,Cat> aa3; //error 二义性
全局定制会覆盖局部定制,局部定制会覆盖主模版