模板初阶
文章目录
- 模板初阶
- 1.模板有啥用
- 2.概念
- ‼️注意点:
- 3.模板有几种
- 4.函数模板
- 4.1创造格式
- 4.2两种用法
- 直接用(隐式实例化)
- 坑点:类型冲突
- 解决方法:
- 特殊表明(显式实例化)
- 必须用显式实例化的情况:
- 4.3特殊情况
- 普通函数和 函数模板 同名
- 强制使用模板:
- 5.类模板
- 5.1格式
- 5.2成员函数的类外定义
- 5.3使用(实例化)
1.模板有啥用
// 交换intvoidSwap(int&left,int&right){inttemp=left;left=right;right=temp;}// 交换doublevoidSwap(double&left,double&right){doubletemp=left;left=right;right=temp;}// 交换charvoidSwap(char&left,char&right){chartemp=left;left=right;right=temp;}有了模板,可以让上面3个函数变成一个⬇️
template<classT>voidSwap(T&x,T&y){T tmp=x;x=y;y=tmp;}2.概念
函数模板在使用时,编译器会根据你传入的类型,自动生成对应类型的具体函数/类。
两个细节:
- 定义模板参数用
typename和class是完全一样的,随便用哪个都行 - 不能用
struct代替class/typename
‼️注意点:
- 模版不建议声明和定义分离到.h 和.cpp 两个文件,会出现链接错误 (实现Stack和list这种的时候)
3.模板有几种
- 函数模版
- 类模版
4.函数模板
4.1创造格式
template<class类型参数1,class类型参数2,...>返回值类型 模板名(形参表){函数体}举例:
template<classT>voidSwap(T&t1,T&t2){T tmp=x;x=y;y=tmp;}4.2两种用法
直接用(隐式实例化)
inta1=10,a2=20;doubled1=10.1,d2=20.2;Add(a1,a2);// 编译器自动推导T为intAdd(d1,d2);// 编译器自动推导T为double坑点:类型冲突
Add(a1, d1); // 编译报错!(a1 是 int, d1 是 double)
解决方法:
- 强转:
Add(a1, (int)d1); // 把double转成int或者Add((double)a1, d1); // 把int转成double - 显示实例化⬇️
特殊表明(显式实例化)
Add<int>(a1,d1);// 强制T为intAdd<double>(a1,d1);// 强制T为double必须用显式实例化的情况:
当编译器无法推导出模板参数类型时必须用:
template<classT>T*func1(intn){returnnewT[n];}intmain(){double*p1=func1<double>(10);//当编译器无法推导出模板参数类型时必须用显式实例化return0;}4.3特殊情况
普通函数和 函数模板 同名
template<classT>TAdd(constT&left,constT&right){return(left+right);}intAdd(constint&left,constint&right){return(left+right)*10;}intmain(){inta1=10,a2=20;cout<<Add(a1,a2)<<endl;// 输出300,调用的是普通函数return0;}输出300,调用的是普通函数
强制使用模板:
Add<int>(a1,a2);// 强制调用模板版本,输出305.类模板
5.1格式
template<classT1,classT2,...,classTn>class类模板名{类内成员定义}举例:只是在类前面加了template<typename T>,然后把所有用到 int 的地方都换成了 T。
template<typenameT>classStack{public:Stack(intn=4):_array(newT[n]),_size(0),_capacity(n){}~Stack(){delete[]_array;_array=nullptr;_size=_capacity=0;}voidPush(constT&x);private:T*_array;size_t _capacity;size_t _size;};5.2成员函数的类外定义
template<classT>voidStack<T>::Push(constT&x){if(_size==_capacity){T*tmp=newT[_capacity*2];memcpy(tmp,_array,sizeof(T)*_size);delete[]_array;_array=tmp;_capacity*=2;}_array[_size++]=x;}- 必须再写一遍
template<class T> - 函数名前面要写成
Stack<T>::Push,而不是Stack::Push‼️
5.3使用(实例化)
- 只有显示实例化。
- 实例化的结果才是真正的类 ,
Stack<double>* p1和Stack<int>* p2是两个不同的类类型‼️
intmain(){// Stack st1;// 错误!Stack是类模板,不是真正的类// 正确!必须在尖括号里指定类型Stack<int>st1;// 存int的栈st1.Push(3);Stack<double>st2;// 存double的栈st2.Push(1.1);//new的方式Stack<double>*pst=newStack<double>;deletepst;return0;}