C++中的模板

xiaoxiao2021-02-28  122

1.模板 模板是泛型编程的基础。即编写与类型无关的逻辑代码,也是一种复用的方式。 C++中的模板分为:模板函数、模板类 (1)模板函数 函数模板格式:template<class/typename 形参名1,class/typename 形参名2,class/typename 形参名n> 例子:实现一个比较两个数是否相符 template <typename T> bool IsEqual(const T& left, const T& right) { return left==right; } 明显的,模板实现了代码的复用,那么模板是如何实现不同类型的参数调用时刚还对号入座呢? 原来,编译器调用模板时,编译器会根据传递的参数自动推演出模板形参的类型,并且自动生成 对应的代码。如下图所示: 需要注意的是: (1)按照以上例子,如果调用IsEqual(1,1.2)时,两个参数不匹配的情况,我们可以做一个变换 <double>IsEqual(1,1.2),这个过程叫做显示实例化 (2)如果模板自己就定义了两个不相同类型的参数,如下 template <typename T1, typename T2> bool IsEqual (const T1& left , const T2& right) {  return left == right; } 如果调用IsEqual(1,1),编译器先检查,看是否有两个参数都是int型的函数IsEqual() 如果有优先调用它,否则再调用模板函数,这就是模板实例化后的函数与原函数构成重载 (2)模板类 模板类格式: template<class/typename 形参名1,class/typename 形参名2,...class/typename 形参名n> class 类名 {...}; 例子:用模板类实现动态顺序表 #include <iostream> #include <assert.h> #include <string> using namespace std; template <typename T> class SeqList { private: T* _a; size_t _size; size_t _capacity; public: SeqList()//构造函数 :_a(NULL),_size(0),_capacity(0) { //cout<<"SeqList()//构造函数"<<endl; } ~SeqList()//析构函数 { if(_a) { delete[] _a; } } SeqList(const SeqList<T>& s)//拷贝构造 { _a=new T[s._size]; for(size_t i=0;i<s._size;i++) { _a[i]=s._a[i]; } _size=s._size; _capacity=_size; } SeqList<T>& operator=(const SeqList<T> s)//赋值运算符的重载 { swap(s._a, _a); swap(s._size,_size); swap(s._capacity,_capacity); return *this; } void CheckCapacity()//判断并且增容 { if(_size==_capacity) { size_t newSize=_capacity?_capacity*2:3;//刚进来增到3,下次每次增2倍容 T* tmp=new T[newSize]; for(size_t i=0; i<_size;i++) { tmp[i]=_a[i];//执行赋值运算符的重载 } delete[] _a; _a=tmp; _capacity=newSize; assert(_a); } } void PushBack(const T& x)//后插 { CheckCapacity(); _a[_size++]=x; } void PopBack()//后删 { _size--; } void Insert(size_t pos, const T& x)//在某个位置前插入一个元素 { CheckCapacity(); assert(pos>=0); for(size_t i=_size;i>pos;i--) { _a[i]=_a[i-1]; } _a[pos]=x; _size++; } void Erase(size_t pos)//删除 { assert(pos>=0); for(size_t i=pos;i<_size-1;i++) { _a[i]=_a[i+1]; } _size--; } T& operator[](size_t pos)//[]重载 { assert((pos>=0)&&(pos<_size)); return _a[pos]; } void Print()//打印元素 { //int i=0; for(size_t i=0;i<_size;i++) { cout<<_a[i]<<" "; } cout<<endl; } }; 需要注意的是: (1)这时候,模板类的类型不是SeqList,而是SeqList<T>. (2)需要开辟空间的时候用new,而不能用realloc,因为用new回调用函数初始化空间,导致每次释放没问题 而realloc第一次进来相当于malloc,空间内容没有初始化,导致释放随机值有问题。 (3)和模板函数类似,在调用模板类的时候,编译器也会根据类型SeqList<T>来模板推演处理,自己 换取相对应类型的模板,如下图所示:
转载请注明原文地址: https://www.6miu.com/read-42789.html

最新回复(0)