一、模板
C++引入模板机制,模板定义:模板就是实现代码重用机制的一种工具,它可以实现类型参数化,即把类型定义为参数, 从而实现了真正的代码可重用性。模版可以分为两类,一个是函数模版,另外一个是类模版。
template <classType> 或者template <typenameType> 新版本允许用关键字typename代替class。(红色标注的为必须关键字,Type可以自己选择命名。)
二、函数模板
需要多个对不同类型使用同一种算法的函数时,可使用函数模板。
举例:
test.c
#include <iostream>
using namespace std;
template <typename T>
T min(T x,T y)
{return (x<y)?x:y ;}
void main()
{
int n1=3,n2=15;
double d1=5.3,d2=3.6;
cout<<"较小整数:"<<min(n1,n2)<<endl;
cout<<"较小实数:"<<min(d1,d2)<<endl;
system("pause"); // 这条语句是必须的,否则控制台一闪而过。
}
结果:
函数模板本身并不会生成函数定义,它只是用于一个生成函数定义的方案。调用min(n1,n2)时编译器才生成min()的一个实例,该实例使用int类型。模板并非函数定义,使用int的模板实例才是函数定义。这种实例化方式称为——隐式实例化。
直接命令编译器创建特定的实例,如:template void swap<int> (int,int);将使用min()模板生成一个使用int类型的实例。句法是:声明所需的种类,用<>符号指示类型,并在声明前加上关键字template.——显示实例化。
显示具体化使用下面的声明template <> void swap<int> (int &,int &);或template <> void swap (int &,int &);与显示实例化不同,它不用swap模板来生成函数定义,而使用独立的、专门的函数定义显示地int类型生成函数定义。显示具体化声明在关键字template后加上<>,显示实例化没有。——显示具体化。
具体化实例:
#include <iostream>
using namespace std;
template <typename T>
void Swap(T& x,T& y); // 注意:Swap不能用swap,这个和标准库的swap定义冲突,会一直报错。
//void Swap(T x,T y); 直接传递参数,不能实现交换。
struct job
{
char name[40];
double salary;
int floor;
};
template <> void Swap<job>(job &,job &); // 显示具体化。
template void Swap(char &,char &); // 具体实例化。
void show(job &j);
void main()
{
short n1=3,n2=15;
Swap(n1,n2); // 隐式实例化。
cout<<"交换两个整数后:"<<"n1:"<<n1<<"n2:"<<n2<<endl;
job a={"xiao yanzi",5699.60,7};
job b={"chou yatou",7899.30,6};
Swap(a,b);
cout<<"交换两个结构体后:"<<endl;
show(a);
show(b);
char g='t',h='e';
Swap(g,h);
cout<<"交换两个字符后:"<<"g="<<g<<"h="<<h<<endl;
system("pause"); // 这条语句是必须的,否则控制台一闪而过。
}
template <typename T>
void Swap(T& x,T& y)
{
T temp;
temp=x;
x=y;
y=temp;
}
template <typename T> // 这句不能少。
void Swap(T * x,T * y,int n)
{
T temp;
int i;
for(i=0;i<n;i++)
{
temp=x[i];
x[i]=y[i];
y[i]=temp;
}
}
template <> void Swap<job>(job &j1,job &j2)
{
double t1;
int t2;
t1=j1.salary;
j1.salary=j2.salary;
j2.salary=t1;
t2=j1.floor;
j1.floor=j2.floor;
j2.floor=t2;
}
void show(job &j)
{
cout<<j.name<<":$"<<j.salary<<"on floor"<<j.floor<<endl;
}
结果:
如果有多个原型时,编译器在选择时,非模板版本将优先于显示具体化和模板版本,显示具体化版本优先于使用模板生成的版本。
试图在同一个编程单元中使用同一种类型的显示实例和显示具体化将出错。
三、重载的函数模板
eg:
#include <iostream>
using namespace std;
template <typename T>
void Swap(T& x,T& y); // 注意:Swap不能用swap,这个和标准库的swap定义冲突,会一直报错。
//void Swap(T x,T y); 直接传递参数,不能实现交换。
template <typename T>
void Swap(T * x,T * y,int n); // 最后一个参数为具体类型int,不是通用类型T。并非所有的模板参数都必须是通用类型。
void main()
{
int n1=3,n2=15;
Swap(n1,n2);
cout<<"交换两个整数后:"<<"n1:"<<n1<<"n2:"<<n2<<endl;
int a1[]={0,6,0,4,2,0,1,3};
int a2[]={0,6,1,0,2,0,1,3};
Swap(a1,a2,8);
int i;
cout<<"交换数组后,a1:";
for(i=0;i<8;i++)
cout<<a1[i]<<",";
cout<<endl;
cout<<"交换数组后,a2:";
for(i=0;i<8;i++)
cout<<a2[i]<<",";
cout<<endl;
system("pause"); // 这条语句是必须的,否则控制台一闪而过。
}
template <typename T>
void Swap(T& x,T& y)
{
T temp;
temp=x;
x=y;
y=temp;
}
template <typename T> // 这句不能少。
void Swap(T * x,T * y,int n)
{
T temp;
int i;
for(i=0;i<n;i++)
{
temp=x[i];
x[i]=y[i];
y[i]=temp;
}
}
结果: