模板(template)是一个将数据类型参数化的工具。模板分为函数模板和类模板两种。
在定义模板的时候不说明某些函数参数或者数据成员的类型,而将它们的数据类型作为模板参数。在使用模板时根据实参的数据类型确定模板参数即数据类型,从而得到模板的一个实例。
函数模板(function template)
函数模板是一种不说明某些参数的数据类型的函数。例如,下面定义了一个可对任何类型变量进行操作(求绝对值)的函数模板。
template <class T> //或写成:template <typename T> T abs(T val) { return val<0 ? -val : val; }
其中,模板定义以关键字template开头,关键字class(或typename)表示其后的标识符T是模板参数(类型参数),用来指定函数模板abs()中参数val的数据类型,随后是函数模板abs()的定义。定义函数模板时,参数化的数据类型T可以用来声明函数的参数和返回值,在函数体中还可以用来声明工作变量。
函数模板被调用时,编译器根据实际参数的类型确定模板参数T的类型,并自动生成一个对应的函数。
函数模板的定义和使用例子如下。
#include <iostream.h> template <class T> //或写成:template <typename T> T abs(T val) { return val<0 ? -val : val; } void main() { int i=100; cout<<abs(i)<<endl; //类型参数T替换为int long l=-12345L; cout<<abs(l)<<endl; //类型参数T替换为long float f=-125.78F; cout<<abs(f)<<endl; //类型参数T替换为float }
定义函数模板时也可以使用多个类型参数,这时,每个类型参数前面都要加上关键字class 或typename,其间用逗号分隔,其形式如下所示。
template <class T1, class T2, class T3>
使用多个类型参数的函数模板的例子如下。
#include <iostream.h> template <class T1, class T2> T1 Max(T1 x, T2 y) { return x>= y ? x :(T1)y; } void main() { int i=100; float f=125.78F; cout<<Max(i,f)<<endl;//类型参数T1替换为int, T2替换为float }
类模板(class template)
类模板是这样一种通用的类:在定义类时不说明某些数据成员、成员函数的参数及返回值的数据类型。类是对对象的抽象,而类模板是对类的抽象,及更高层次上的抽象。类模板称为带参数的类,也称为类工厂(class factory),它可用来生成多个成员相同而某些数据成员、成员函数的参数及返回值的数据类型不同的类型参数。
类模板在定义其成员函数时要用到类模板的类型参数T。如下例定义了含有一个类型参数的模板。
template <class T> //或写成: template <typename T> class MyTemClass { private: T x; //类型参数T用于声明数据成员 public: void SetX(T a) { x=a; } //类型参数T用于声明成员函数的参数 T GetX() {return x;} //类型参数T用于声明成员函数的返回值 };
如果在模板类的外部定义模板类的成员函数,必须采用如下形式:
template <class T> //不能省略template模板声明 MyTemClass<T>::SetX(T a) { x=a; }
类模板通过使用类模板声明对象时所给出的实际数据类型确定类型参数的数据类型。以下利用类型参数为int的类模板声明了一个对象intObject.
MyTemClass<int> intObject;
对于上面的对象声明,编译器首先用int替换类模板中的类型参数T,生成一个所有数据类型已确定的类(模板类),然后再利用这个类声明一个对象。
定义类模板时同样额可以使用多个类型参数,并且,类模板的类型参数可以含有已确定类型的参数,如下所示:
template <class T1, int i, class T2> //含有已确定类型int参数i class MyTemClass { ... //类模板的成员声明 };
这时,声明类模板的对象应采用如下形式:
MyTemClass<int, 100, float> MyObject;
使用多个类型参数的类模板的例子如下。
#include <iostream.h> template <class T1, class T2> //使用2个类型参数 class MyTemClass //定义类模板 { private: T1 x; T2 y; public: MyTemClass(T1 a, T2 b) {x=a; y=b;} //构造函数 void ShowMax() //输出最大的数据成员 { cout<<"MaxMember="<<(x>=y ? x : y)<<endl; } }; void main() { int a=100; float b=123.45F; MyTemClass<int, float> mt(a,b); //声明类模板的对象 mt.ShowMax(); }