泛型编程与面向对象编程一样,都依赖于某种形式的多态性。面向对象编程所依赖的多态性称为运行时多态性,泛型编程所依赖的多态性称为编译时多态性或者参数式多态性。
在泛型编程中,我们所编写的类和函数都能多态地用于跨越编译时不相关的类型,一个类或者一个函数可以用来操纵多种类型的对象。标准库中的容器、迭代器和算法是很好的泛型编程的例子。
模板是泛型编程的基础。
模板函数的例子
首先来看一段用于比较大小的代码。
#include<iostream> using namespace std; int compare(const int &v1,const int &v2); double compare(const double &v1,const double &v2); int main() { cout<<"Hello"<<endl; cout<<compare(1,2)<<compare(1.2,3.2)<<endl; return 1; } int compare(const int &v1,const int &v2) { cout<<"compare int"<<endl; if (v1<v2) return -1; if(v2<v1) return 1; return 0; } double compare(const double &v1,const double &v2) { cout<<"compare double"<<endl; if (v1<v2) return -1; if(v2<v1) return 1; return 0; }
编译运行之后的结果如下:
上面的程序中,compare函数被重载,由于参数不同,最终调用的函数会自动匹配。
现在假设我需要compare函数不仅要支持int和double,还要支持float,string…继续重载么,No。现在就需要模板函数了。
对源程序进行修改。
#include<iostream> #include<string> using namespace std; template <typename T> int compare(const T &v1,const T &v2) { if(v1<v2) return -1; if(v1>v2) return 1; return 0; } int main() { cout<<"Hello"<<endl; string a="zoo",b="tiger"; cout<<compare(a,b)<<compare(1,2)<<compare(1.2,3.2)<<endl; return 1; }
运行结果:
这就是传说中的模板函数了,使用函数模板时,编译器会推断哪个模板实参绑定到模板形参。一旦编译器确定了实际的模板实参,就称它实例化了函数模板的一个实例。
编译器使用实参代替相应的模板形参并编译改版本的函数。
所以上面实际是编译了三个compare的版本。脏活累活编译器已经帮我们干了。
使用的时候要注意用作模板形参的名字不能在模板内部重用。
载函数模板内部完成的操作限制了可用于实例化改函数额度类型。程序员的责任是:保证用作函数实参的类型实际上支持所用的任意操作,以及保证在模板使用那些操作的环境中那些操作运行正常。
在使用模板的时候要注意以下几点:
1)对实参类型的要求尽可能少;
2)模板形参是const引用;
3)函数体中的测试只用<比较。
用template inline替代#define
我们常用#define来定义宏,比如:
#define CALL_WITH_MAX(a,b) f((a)>(b))?(a):(b);
上面的语句虽然很小心地打了很多小括号,但是…如果语句是这样:
int main() { int a=5,b=3; CALL_WITH_MAX(++a,b); cout<<"a"<<a<<"b"<<b<<endl; CALL_WITH_MAX(++a,b+10); cout<<"a"<<a<<"b"<<b<<endl; cout<<"Hello"<<endl; return 1; }
运行后的结果会是这样:
第一次调用CALL_WITH_MAX,a加了两次,第二次a只加了一次,所以,还是不安全。
下面用模板来实现一下。
#include<iostream> using namespace std; //#define CALL_WITH_MAX(a,b) (a)>(b)?(a):(b); template <typename T> inline T call_with_max(const T &a,const T &b) { return(a>b?a:b); } int main() { int x,a = 5,b = 3; x = call_with_max(++a,b); cout<<"a"<<a<<"b"<<b<<"x"<<x<<endl; x = call_with_max(++a,b+10); cout<<"a"<<a<<"b"<<b<<"x"<<x<<endl; return 1; }
运行结果:
这是我们预期的结果。
类模板
下面是一个简单的数组类模板。
#include<iostream> #include <stdlib.h> using namespace std; template <class T> class Array { public: Array(int); T & operator[] (int); int getSize(); ~Array(); private: T *a; int size; int errorValue; Array(); }; template<class T> Array<T> ::Array(int n) { a = new T[size = n]; errorValue = -1; } template<class T> Array<T> ::~Array() { delete []a; } template<class T> T& Array<T>::operator[](int index) { if(index < 0 || index >= size) { cout << "Out of boundry" << endl; exit(1); } return a[index]; } template<class T> int Array<T>::getSize() { return size; } int main() { Array<double> a(10); Array<int> b(20); cout<<"a.size:"<<a.getSize()<<endl; for(int i=0;i<b.getSize();i++) cout<<b[i]<<endl; return 1; }
运行结果:
转载于:https://blog.51cto.com/8672742/1368318
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/110184.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...