1.模板基础
C++提供了函数和类机制,可用来设计可重用软件。而模板功能提供了在函数和类中将类型作为参数的能力。有了这种能力,我们就可以设计具有通用类型的函数或类,而编译器会在编译是将通用类型确定为一种具体的类型。
我们从一个简单的例子开始,来看一下模板机制的必要性。假设我们分别想求两个整数和两个double型值中较大的,那么我们需要写两个重载函数,如下所示:
int maxValue(int value1,int value2)
{
if(value1>value2)
return value1;
else
return value2;
}
double maxValue(double value1,double value2)
{
if(value1>value2)
return value1;
else
return value2;
}
这两个函数几乎是一样的,差别仅仅在于使用的类型不同。如果能定义一个通用类型的函数就好了,那么就能节省存储空间,并能使程序更易于维护。C++允许定义具有通用类型的函数模板。下面就开始介绍本文的重点内容,函数模板和类模板。
2.模板函数
还是上面求较大值的例子,我们可以用C++中的模板函数来实现。如下:template<typename T>
T maxValue(T value1,T value2)
{
if (value1>value2)
return value1;
else
return value2;
}
我们可以分别调用maxValue函数来求两个int和double值中的较大者。模板函数的定义是以关键字template开始的,后面跟着一个参数列表。如上例中的代码,template<typename T>,以上面代码开始了函数模板maxValue的定义。这行代码也称为模板前缀,此处的T是类型参数。习惯上,我们用单个大写字母(如T)来表示类型参数。
3.模板类
模板类的语法基本上与模板函数的相同。应在类声明前加上模板前缀,就像在函数模板声明前添加模板前缀一样。在类中,类型参数可以如同任何普通类型一样使用。模板类中的构造函数和成员函数的定义与普通类是一样的,唯一的区别在于它们都是模板函数。因此,需要在函数头前添加模板前缀。下面是实现栈的一个简单例子。
template<typename T>
class stack
{
public:
stack();
bool empty();
T peek();
void push(T value);
T pop();
int getSize();
private:
T *elements;
int size;
int capacity;
void ensureCapacity();
};
template<typename T>
stack<T>::stack(): size(0),capacity(16)
{
elements=new T[capacity];
}
template<typename T>
bool stack<T>::empty()
{
return (size==0);
}
template<typename T>
T stack<T>::peek()
{
return elements[size-1];
}
template<typename T>
void stack<T>::push(T value)
{
ensureCapacity();
elements[size++]=value;
}
template<typename T>
void stack<T>::ensureCapacity()
{
if(size>=capacity)
{
T *old=elements;
capacity=2*size;
elements=new T[size*2];
for(int i=0;i<size;i++)
elements[i]=old[i];
delete old;
}
}
template<typename T>
T stack<T>::pop()
{
return elements[--size];
}
template<typename T>
int stack<T>::getSize()
{
return size;
}