C++为什么要引入函数模板呢?
举个例子说明一下:
int swap(int a,int b)
{
int t =a;a=b;b=t;
}
float swap (float a,float b)
{
float t =a;a=b;b=t;
}
double swap(double a,double b)
{
double t =a;a=b;b=t;
}
char swap (char a,char b)
{
char t =a;a=b;b=t;
}
上面定义了四个重载函数swap,观察四个重载函数,发现除了类型不同,四个函数的函数体的写法完全一样。考虑,将四个函数的类型使用T代替,则上面四个函数的写法就完全一致了:
T swap(T a,T b)
{
T t =a;a=b;b=t;
}
观察变化:四个重载函数变成了同一个函数写法。
C++中提供了语法来描述上面的函数——函数模板。
下面C++函数模板定义:
template <class 模板类型参数1,class 模板类型参数2 ,…>
返回值类型 函数模板名(模板参数表)
{
函数模板体
}
要求:定义中的所有的模板类型参数必须出现在函数模板的模板参数表中,否则编译将会报错。
上面的四个交换重载函数可以使用函数模板来描述:
template <class T>
void swap(T a, T b)
{T t=a;a=b;b=t;
}
有了上面函数模板swap定义,则前面的swap重载函数可以不需要定义了!
例子:
template <calss T1,class T2>
void f(int a,T1 b)//这个模板定义将出错,因为类型参数T2没有出现在模板参数表 //中
{...
}
函数模板定义了一簇函数,因此函数模板不是函数,但可以通过对函数模板进行实例化生成具体的函数,用函数模板实例化生成的具体函数称为模板函数。
如何对函数模板进行实例化?
函数模板的实例化采取隐式实例化方式,也即不需要程序员去实现,在编译阶段由编译器完成实例化并且生成相应的模板函数。
实例化函数模板的调用语法与普通函数的调用是一致的:
函数模板名(实际参数表);
以上函数模板调用语句编译器的解释:
(1)首先检查是否有类型参数个数完全一致的函数定义,如果有,则使用该函数的函数体进行调用,否则进入(2)
(2)检查通过类型隐式转换后是否存在(1)的情况,如果有,则隐式转换后选择 (1)的方式进行调用,否则进入(3)
(3)检查是否存在函数模板,如果有则生成实际参数类型的对应模板函数再进行调用,否则检查通过类型隐式转换后是否存在函数模板,如果有,则生成相应的模板函数,否则调用失败。
简单例子:
定义函数模板swap:
template <class T>
void swap(T a, T b)
{T t=a;a=b;b=t;
}
swap(100,200);//编译器生成模板函数swap(int ,int),并调用
swap(100,‘a’);//编译器将char类型参数隐式转换为int,编译器生成模板函数 //swap(int ,int),并调用
swap(100.4,300)//编译器将int类型参数隐式转换为double,编译器生成模板函 //数 swap(double,double),并调用
应用举例:
请写一个函数模板Sort(T *a,int n)对数组a中n个元素进行排序
函数模板Sort代码:
#include"iostream"
#include"algorithm"
using namespace std;
template<class T1,class T2>
void Sort(T1 *a,T2 num)
{
T1 temp;
for(int i=0;i<num-1;i++)
{
for(int j=i+1;j<num;j++)
{
if(a[j]>a[i])
{
temp=a[i];
a[i]=a[j];
a[j]=temp;
}
}
}
}
template <class T1,class T2>
void Print(T1 *a,T2 num)
{
for(int i=0;i<num;i++)
cout<<a[i]<<ends;
}
int main()
{
int *pi;
char *pj;
double *pk;
int num;
cout<<"请输入数据个数:"<<endl;
cin>>num;
pi=new int[num];
pj=new char[num];
pk=new double[num];
cout<<"请输入第一组整型数据:"<<endl;
for(int i=0;i<num;i++)
{
cin>>pi[i];
}
cout<<"请输入第二组字符型数据:"<<endl;
for(int i=0;i<num;i++)
{
cin>>pj[i];
}
cout<<"请输入第三组双精度数据:"<<endl;
for(int i=0;i<num;i++)
{
cin>>pk[i];
}
cout<<endl<<"排序前数据:";
Print(pi,num);
cout<<endl<<"排序后数据:";
Sort(pi,num);
Print(pi,num);
cout<<endl<<endl<<"排序前数据:";
Print(pj,num);
cout<<endl<<"排序后数据:";
Sort(pj,num);
Print(pj,num);
cout<<endl<<endl<<"排序前数据:";
Print(pk,num);
cout<<endl<<"排序后数据:";
Sort(pk,num);
Print(pk,num);
return 0;
}