C++提供的函数模板可以定义一个对多种类型变量进行操作的函数,从而大大增强函数设计的通用性。使用函数模板的方法是先说明函数模板,然后在实例化相应的模板函数进行调用执行。
函数模板的一般说明形式:
template 类型形参表 返回类型 函数名(形参表) { 函数体; }其中,类型形参表可以包含基本数据类型,也可以包含类类型。类型形参需要加上class / typename 每一个类型形参都需要使用class / typename。
template <class T> T Abs(T x) { if(x < 0) { return -x; } return x; }函数模板只是说明,不能直接执行,需要实例化成模板函数才能执行 当编译系统发现有一个函数调用: 函数名(形参表) C++将根据实参表中的数据类型生成一个相对应的重载函数,即模板函数
#include<iostream> using namespace std; template <class T> T Min(T x,T y) { if(x < y) { return x; } else { return y; } } int main(void) { int n1 = 2,n2 = 10; double d1 = 1.5,d2 = 5.6; cout<<"较小整数:"<<Min(n1,n2)<<endl; cout<<"较大整数:"<<Min(d1,d2)<<endl; return 0; }当调用Min(n1,n2)时,创建相应的模板函数,也就是函数模板的实例化,由于参数的类型是int ,所以int会代替占用占位符T。
模板函数的说明和定义必须是全局作用域。模板不能被说明为类的成员函数。模板类型并不具有隐式的类型转换,所以,模板函数T的各个参数之间的数据类型必须保持一致。
可以在函数模板形参表和对函数模板的调用中使用类的类型和其他用户定义的类型。需要对重载模板函数中对类变量产生作用的基本操作符。
#include<iostream> using namespace std; class coord { private: int x,y; public: coord(int x1,int y1) { x = x1,y = y1; } int getX() { return x; } int getY() { return y; } int operator<(coord &c);//重载为类的成员函数 }; int coord::operator<(coord &c)//"<" 运算符重载函数 函数说明 { if(x < c.x && y < c.y) { return 1; } return 0; } //使用模板函数 如果参数列表含有类类型 template <class obj>//函数模板定义说明 obj &Min(obj &o1, obj &o2) { if(o1 < o2) { return o1; } else { return o2; } } int main(void) { coord c1(5,11); coord c2(6,18); coord c3 = Min(c1,c2); cout<<c3.getX()<<" "<<c3.getY()<<endl; double d1 = 3.1; double d2 = 9.2; cout<<"较小的数:"<<Min(d1,d2)<<endl; return 0; }要找到两个对象中的较小者,必须重载“<"
类模板其实是函数模板的推广。类模板再说明一个类时,能够将用于实现这个类所需要的数据类型参数化。一个类模板是对一个对象特性更加一般的抽象。
类模板的一般说明形式:
template 类型形参表 class 类名 { //类 }; template 类型形参表 返回类型 类名 类型名表::成员函数1(形参表) { //成员函数定义体 } template 类型形参表 返回类型 类名 类型名表::成员函数2(形参表) { //成员函数定义体 } template 类型形参表 返回类型 类名 类型名表::成员函数3(形参表) { //成员函数定义体 }类型形参表与函数模板中的意义一样,类型形参表可以包含表达式参数
template <class T1,int exp1,class T2> class someclass { //类定义语句 };同样,类模板那是不能直接使用的,必须先实例化相应的模板类,要定义改模板类才能使用。 建立类模板之后,创建类模板实例:
类名 类型实参表 对象表;其中,类型实参表应该与类模板类型形参表匹配。
#include<iostream> using namespace std; template <class T> class Sample { private: T d; public: Sample(T i) { d = i; } void disp() { cout<<"d = "<<d<<endl; } }; int main(void) { Sample <int> obj1(10);//类名 类型实参表 对象表 Sample<int>为模板类 Sample <char *> obj2("China!"); //Sample<char *>为模板类 obj1.disp(); obj2.disp(); return 0; }上述程序中,类模板Sample<T>中定义了一个一友元函数实现的运算符重载,即friend Sample<T> operator+(Sample<T> s1, Smaple<T> s2)