下面是一段类声明:
typedef unsigned long Item
class Stack
{
private:
enum { MAX = 10 };
Item items[MAX];
int top;
public:
Stack();
bool isempty() const;
bool isfull() const;
bool push(const Item &item);
bool pop()(Item &item);
};
采用模板时,将使用模板定义替换Stack声明,使用模板成员函数替换Stack的成员函数。和模板函数一样采用下面这样的代码开头:
template <class Type>
关键字template告诉编译器要定义一个模板,较新的c++实现允许用typename代替class,template <typename Type>,我们可以泛型名字代替Type。
所以对于Stack类来说,Item items[MAX]; 应该改成 Type items[MAX];同样,可以使用模板成员函数替换原有类的方法:
bool Stack::push(const Item &item)
{
...
}
应该改成:
template <class Type>
bool Stack<Type>::push(const Type &item)
{
...
}
如果在类声明中定义了方法(内联定义),则可以省略模板前缀和类限定符。由于模板不是函数,他们不能单独编译。模板必须与特定的模板实例化请求一起使用。为此,最简单的办法是将所有模板信息放在一个头文件中,并要使用这些模板的文件中包含该头文件。
模板类声明:
//stacktp.h -- a stack template
#ifndef STACKTP_H_
#define STACKTP_H_
template <class Type>
class Stack
{
private:
enum { MAX = 10 };
Type items[MAX];
int top;
public:
Stack();
bool isempty();
bool isfull();
bool push(const Type &item);
bool pop(Type &item);
};
template <class Type>
Stack<Type>::Stack()
{
top = 0;
}
template <class Type>
bool Stack<Type>::isempty()
{
return top == 0;
}
template <class Type>
bool Stack<Type>::isfull()
{
return top == MAX;
}
template <class Type>
bool Stack<Type>::push(const Type &item)
{
if (top < MAX)
{
item[top++] = item;
return true;
} else {
return false;
}
}
template <class Type>
bool Stack<Type>::pop(Type &item)
{
if (top > 0)
{
item = items[--top];
return true;
} else {
return false;
}
}
#endif
使用模板类:
仅在程序包含模板并不能生成模板类,而必须请求实例化。为此,需要声明一个类型为模板类的对象,方法是使用所需的具体类型替换泛型名。例如,下面的代码创建两个栈,一个用于存储int,另一个用于存储string对象:
Stack<int> kernels;
Stack<string> colonels;
编译器按照Stack<Type>模板来生成两个独立的类声明和两组独立的类方法。泛型标识符——这里的Type称为类型参数(type parameter),这意味着他们类似于变量,但是赋给他们的不能是数字,只能是类型。注意,必须显示的提供所需的类型,这与常规的函数模板时不同的,因为编译器可以根据函数参数类型来确定要生成哪种函数:
template <class T>
void simple(T t) { cout << t << '\n'; }
...
simple(2); //这里会使用void simple(int);
simple("two");//这里会使用void simple(const char *);