泛型编程:编写与类型无关的代码,模板是泛型编程的基础,模板分为模板函数和模板类。
函数模板
函数模板与类型无关,在使用时编译器根据传入的实参帮我们推演出特定类型的函数版本(产生模板特定类型的过程称为模板的实例化)。
//函数模板定义格式
template<typename T>
//template<class T>
//typename是用来定义模板参数的关键字,也可以用class代替(这里不能用struct)
void swap(T& x,T& y)
{
T temp = x;
x = y;
y = temp;
}
void test()
{
int a, b;
a = 10;
b = 20;
double c, d;
c = 1.1;
d = 2.2;
//函数模板的实例化
//隐式实例化:
swap(a,b);
swap(c,d);
//swap(a,d); //此处编译器无法确定到底该将T确定为int还是double类型而报错
//处理方式:显示实例化
swap<double>(a,d);
}
编译器的基层处理:
很清楚地看到两次调用call的是不同的函数,这两个不同的函数真是编译器根据我们传入的实参帮我们推演出的两个不同的函数模板类型。
类模板
这里实现一个完整的Seqlist(顺序表)模板,能存储int、double类型的元素,还能存储string类对象:
//类名:Seqlist
//类型:Seqlist<T>
template<class T>
class Seqlist
{
public:
Seqlist() //构造函数
:_array(NULL)
,_size(0)
,_capacity(0)
{}
~Seqlist() //析构函数
{
if (_array)
{
delete[] _array;
_size = _capacity = 0;
}
}
//Seqlist s2 = s1;
//Seqlist(const Seqlist& s) //把参数类型换成类名也是可以的,不建议用
Seqlist(const Seqlist<T>& s) //拷贝构造函数
{
if (s._size)
{
_array = new T[s._size];
_size = _capacity = s._size;
//memcpy(_array, s._array, sizeof(T)*s._size); //T == string就不行
for (size_t i = 0; i < _size; ++i)
{
_array[i] = s._array[i];
}
}
else
{
_array = NULL;
_size = _capacity = 0;
}
}
//s2 = s1;
//Seqlist<T>& operator=(const Seqlist& s) //把参数类型换成类名也是可以的,不建议用
Seqlist<T>&