模板
泛型编程
编写与类型无关的通用代码,是代码的服用。模板是泛型编程的基础。
模板
- 函数模板
- 类模板
函数模板
函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型模板。
函数模板的格式
template<typename T1,....typename T2,typename T3>
返回值类型 函数名(参数列表){}
typemname 用来定义模板参数的关键字 ,也可以使用class ,但不能使用struct替代class
template<class T>
void swap(T& x1,T& x2)
{
T tmp=x1;
x1=x2;
x2=tmp;
}
int main()
{
int a=0,b=1;
double aa=1.11,bb=2.22;
swap(a,b);
swap(aa,bb); //两者没有调同一个swap,仍旧存在两个swap,由编译器生成
}
//编译阶段,编译器根据传入的实参类型来推演生成相对应的函数。
模板的实例化
用不同类型的参数使用模板函数时,称为函数模板的实例化
- 隐式的实例化:让编译器根据实参推演模板的实际类型
tmplate<class T> //模板参数的声明
int Add(T& x,T& y)
{
return x+y;
}
int main()
{
int a=1,b=2;
double c=9.0,d=2.3;
//隐式的实例化
Add(a,b);
Add(c,d);
//Add(a,c) 不能编译通过,a被推导为int型,c被推导为double型在模板种编译器一般不会进行类型转换操作
}
- 显示的实例化:在函数名后的<>种指定模板参数的实际类型
int main()
{
int a=0;
double b-9.0;
Add<int>(a,b);
return =0;
}
//当函数为无参时,只能使用显示实例化
函数模板的匹配原则
- 一个非模板函数可以和一个同名参数模板同时存在,而且该函数模板可以被实例化为这个非函数模板
- 如果非模板函数和模板函数条件相同,优先使用非模板函数,如果模板函数可以产生一个更好的匹配函数,那将选择模板
- 显示指定一个空的模板实参列表,该语法告诉编译器自由模板才能匹配这个调用,而且所有的模板参数都应该根据实参演绎出来
Add(1,2); //调用现成的
Add<int>(1,2); //调用模板
Add(1,2.2);//调用模板
Add<>(1,2)//只能调用模板
类模板
类模板定义的格式
template<class T1,class T2,……class Tn>
class 模板名
{
//类成员变量
}
类模板定义的实例化:
实现一个动态顺序表:
#include <iostream>
#include <string.h>
#include <stdlib.h>
using namespace std;
//
template<class T>
class Vector{
public:
Vector(size_t capacity)
:_pdata(new T[capacity])
,_size(0)
,_capacity(capacity)
{};
void pushback(int key)
{
if(_size==_capacity)
CheckCapacity();
_pdata[_size++]=key;
}
void CheckCapacity()
{
T* tmp=new T[_capacity*2];
memcpy(tmp,_pdata,sizeof(T)*_capacity*2);
_capacity*=2;
delete[] _pdata;
_pdata=tmp;
}
void popback()
{
--_size;
}
~Vector()
{
if(_pdata)
delete[] _pdata;
}
void Print()
{
for(int i=0;i<_size;i++)
cout<<_pdata[i]<<" ";
}
T* operator[](int n)
{
return _pdata[n];
}
private:
T* _pdata;
int _size;
int _capacity;
};
int main ()
{
Vector<int> L(4);
L.pushback(1);
L.pushback(2);
L.pushback(3);
L.pushback(4);
L.pushback(4);
L.pushback(4);
L.Print();
Vector<double> S(3);
S.pushback(5.3);
S.pushback(6.6);
S.pushback(7.9);
S.pushback(8.4);
S.pushback(9.0);
S.Print();
}1
operator[](size_t pos)
{
return _a[pos];
}