最近写了一堆的Qt程序,突然想要重新搞一遍STL。这一次要正规起来,认真做好笔记的记录工作。
模版,template,出现的目的就在于减少程序员的工作量,将一些功能相似的函数或者类抽象出来,成为一个模板函数或者模板类。
比如最简单的例子,实现交换两个数的函数swap。
void swap(int& a, int& b)
{
int tmp = a;
a = b;
b = tmp;
}
这个函数可以将两个整数进行交换。但是如果要交换两个实数呢,一般而言,需要重新定义一个函数swap。
void swap(double& a, double& b)
{
double tmp = a;
a = b;
b = tmp;
}
这样,如果还要交换两个字定义类的内容,又需要实现想对应的参数版本的swap函数。
为了避免这种简单的重复劳动,C++引入了模板机制,使得程序员可以将注意力从数据类型和数据结构上转移到算法和创新上来。
下面是使用模板来重新实现的swap函数版本。
template <class T>
void swap(T& a, T& b)
{
T tmp = a;
a = b;
b = tmp
}
其中,template关键字声明使用模板,class关键字声明一种抽象的数据类型T,函数体里面的类型T在实例化时就会使用具体的数据类型来代替。实际中,class关键字可以和typename关键字互换,并且推荐使用typename关键字。
C++使用的模板机制主要体现在两方面:类模板和函数模版。对应起来就是数据结构和算法,基本上实现了数据结构和算法的分离。
类模板:
template <class T>
class vector
{
T* v;
int sz;
public:
vector(int s) { v = new T[sz = s]; }
~vector() { delete [] v; }
T& operator[] (int i) { return v[i]; }
int get_size() { return sz; }
};
类模板的使用方式基本上与普通类的使用方式一致。
在代码中使用
vector<int> int_vector(10);
vector<char> char_vector(10);
vector<shape> shape_vector(10);
就可以分别特例化出三个类型的模板类实例。
模板函数:
参见前面的swap函数模板。同类模板一样,在实际使用中需要用到某种特定数据类型的模板函数时,该类型的模板函数才会特例化。
注:在编写自定义的类模板或者函数模板时,通常的做法是将声明部分放在A头文件中,将实现放在B头文件中,并且将B头文件包含到A头文件,这样就可以实现声明与实现的分离,同时可以在特例化类模板或者函数模板时编译器不会报错。