1.函数重载
仅仅函数的返回值类型不同不能实现重载;
参数只有const和非const类型的可以实现重载;
2.模板
如果有多个原型,则编译器在选择原型时,非模板版本优先于显示具体化和模板版本,而显式具体化优先于使用模板生成的版本。
void swap(job &,job &)//非模板
/***************************/
template<typename T>
void swap(T &,T &); //模板版本
/****************************/
template<>void swap<job>(job &,job &)//显式具体化版本
模板的显示实例化:
对与一个函数:
template<class T>
void swap(T &a,T &b)
{
T temp;
temp=a;
a=b;
b=temp;
}
//显示实例化:
template void swap<int>(int,int); //无需给这个函数重新编写函数体,这只是个声明
为什么要显式实例化?
主要是提高效率,当显式实例化模板时,在使用模板之前,编译器根据显式实例化制定的类型生成模板实例,这就相当于本程序有一个:
void swap(int &a, int &b)
{
int temp;
temp = a;
a = b;
b = temp;
}
这样的话,每次调用swap(a,b)的时候,都会重新生成该类型的代码,可以提高效率。
除了在声明的时候显式实例化,还可以在函数使用的过程中实现显式实例化,例如:
template <class T>
T Add(T a,T b)
{
return a+b;
}
...
int m=6;
double x=10.2;
cout<<Add<double>(x,m)<<endl; //这里的m类型不匹配,可以在调用的过程中显式实例化实现强制类型转换
//如果对下边这个函数实现显式实例化会如何?
void swap(T &a,T &b)
{
T temp;
temp=a;
a=b;
b=temp;
}
int m=6;
double x=10.2;
cout<<Add<double>(m,x)<<endl;//不幸的是第一形参是指向double的地址,不能指向int类型
模板的显式具体化:
template<>void swap<int>(int &,int &);
通常又有另外一些特殊的情况,不能直接用泛型模板展开实现,这就需要针对某个特殊的类型或者某一类的类型,从而实现一个特例的模板—–即模板特化。例如:
当T是一个struct类型的时候,它的交换就无法进行,所以我们需要针对这种类型专门写一个函数,只有当T为这种struct类型的时候,才会调用这个特化函数。
显式具体化在声明的时候使用前缀template和template<>,用来区分显式实例化和具体化。
显示实例化和具体化总结:
template<class T>
void swap(T &,T&)
template<>void swap<job>(job &,job &);
int main()
{
template void swap<char>(char &,char &);
short a,b;
...
swap(a,b);//隐式实例化,相当于swap(short,short);
job n,m;
swap(m,n);//显式具体化
...
char g,h;
swap(g,h);//显式具体化
}