模板是泛型编程的基础,即与类型无关的逻辑代码。
利用模板机制可以显著减少冗余信息,能大幅度地节约程序代码,进一步提高面向对象程序的可重用性和可维护性。
模板是实现代码重用机制的一种工具,它可以实现类型参数化;
模板分为函数模板和类模板。
为了使用函数名相同,参数不同,返回值可同可不同的函数时,我们起初用了重载的方式。
#include<iostream> using namespace std; int add(int a,int b) { return a+b; } double add(double a,double b) { return a+b; } int main() { cout<<"ret1="<<add(1,2)<<endl; cout<<"ret2="<<add(2.3,3.0)<<endl; getchar(); return 0; }
但是运用重载的方式写起来比较不方便,尤其是重载的函数较多时,为了解决这类问题,我们用函数模板来实现这种功能。
#include<iostream> using namespace std; template <class T> T add(const T& a,const T& b) { cout<<"type:"<<typeid(a).name()<<endl; //显示类型 return a+b; } int main() { cout<<"ret1="<<add(1,2)<<endl;//还可以显示实例化,显示指定T为int,即add<int>(1,2) cout<<"ret2="<<add(2.3,3.0)<<endl; //add<double>(2.3,3.0) getchar(); return 0; }
以上函数中函数参数类型都是相同的,当我们遇到形如:add(1,2.3);一个参数为int,一个参数为double型,此时我们可以这样定义:
template <class T1,class T2> T add(const T1& a,const T2& b) { return a+b; }
当然,肯定有人会想,模板函数可以构成重载吗? 答案是肯定的。
#include<iostream> using namespace std; int add(int a,int b) { return a+b; } double add(double a,double b) { return a+b; } template <class T> T add(const T& a,const T& b) { cout<<"type:"<<typeid(a).name()<<endl; return a+b; } int main() { cout<<"ret1="<<add(1,2)<<endl; cout<<"ret2="<<add(2.3,3.0)<<endl; getchar(); return 0; }
当模板构成重载,调用add的函数时,它会先调用非模板类的函数,性能比较高;而模板函数内部还得调用,有推演过程判断它是什么类型,效率上会有所降低。
2.模板类
对于普通函数来说,我们拿typedef重定义一个类型,当需要改的时候,需要将int改掉就可以了;
typedef int DataType; class SEQLIST { private: DataType *data; };
而我们为了适应更多的类型,于是引入了模板类,我们这样定义,体现了其高度复用的优势:
template<class T> class SeqList { private: T* data; };
写一个模板类实现SeqList的动态顺序表吧:
#include<iostream> using namespace std; template <class T> class SeqList { public: SeqList() :_data(NULL) ,_size(0) ,_capacity(0) {} SeqList(const SeqList<T>& s); SeqList<T>& operator=(const SeqList<T>& s); ~SeqList() { if(_data != NULL) { delete[] _data; } } void CheckCapacity(); void PushBack(const T& d); void PopBack(); void PushFront(const T& d); void PopFront(); void Print(); private: T *_data; int _size; int _capacity; }; template <class T> SeqList<T>::SeqList(const SeqList<T>& s) { _data = new T[s._size*sizeof(T)]; int i = 0; for(i = 0;i < s._size; i++) { _data[i] = s._data[i]; } _size = s._size; _capacity = s._capacity; } template <class T> SeqList<T>& SeqList<T>::operator=(const SeqList<T>& s) { int i = 0; if(this == &s) { return *this; } _size = s._size; _capacity = s._capacity; delete _data; _data = new T[_capacity]; for(i = 0; i < _size; i++) { _data[i] = s._data[i]; } return *this; } template <class T> void SeqList<T>::CheckCapacity() { if(_size == _capacity) { T* tmp = new T[_capacity*2+3]; //memcpy(tmp,_data,_size*sizeof(T)); int i = 0; for(i = 0; i < _size; i++) { tmp[i] = _data[i]; } delete[] _data; _data = tmp; _capacity = _capacity*2+3; } } template <class T> void SeqList<T>::PushBack(const T& d) { CheckCapacity(); _data[_size] = d; _size++; } template <class T> void SeqList<T>::PopBack() { CheckCapacity(); _size--; } template <class T> void SeqList<T>::PushFront(const T& d) { int i ; CheckCapacity(); for(i = _size; i > 0; i--) { _data[i] = _data[i-1]; } _data[0] = d; _size++; } template <class T> void SeqList<T>::PopFront() { int i; CheckCapacity(); for(i = 0; i < _size; i++) { _data[i] = _data[i+1]; } _size--; } template <class T> void SeqList<T>::Print() { int i = 0; for(i = 0; i < _size; i++) { cout<<_data[i]<<" "; } cout<<endl; } int main() { SeqList<int> seq; SeqList<int> seq1; cout<<"seq:"<<endl; cout<<"尾插1234"<<endl; seq.PushBack(1); seq.PushBack(2); seq.PushBack(3); seq.PushBack(4); seq.Print(); cout<<"尾删"<<endl; seq.PopBack(); seq.Print(); cout<<"头删"<<endl; seq.PopFront(); seq.Print(); cout<<"seq2:"<<endl; SeqList<int> seq2(seq); seq2.Print(); cout<<"头插567"<<endl; seq.PushFront(5); seq.PushFront(6); seq.PushFront(7); seq.Print(); seq1 = seq; cout<<"seq1:"<<endl; seq1.Print(); getchar(); return 0; }
模板就说到这里啦,有好的建议还希望大家提出来,欢迎来访哦。