定义模板类
先看一个之前自定义的Stack类
// 别名
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);
};
模板类以下面这样的代码开头:
template <class Type>
关键字template告诉编译器, 将要定义一个模板, 尖括号中的内容相当于函数的参数列表. 可以把关键字class看作是变量的类型名, 该变量接收类型作为其值, 把Type看做是该变量的名称.
这里的class并不意味着Type必须是一个类, 而只是表明Type是一个通用的类型说明符, 在使用模板时, 将使用实际的 类型替换它, 也可以使用typename替换class:
template <typename Type>
同样, 可以使用模板成员函数替换原有类的类方法. 每个函数头都将以相同的模板声明打头:
template <class Type>
同样应使用泛型名Type(可以替换成T等其他字符)替换typedef标识符Item, 另外, 还需要将类限定符从Stack::改为Stack<Type>::, 例如:
bool Stack::push(const Item & item)
{
...
}
应改为:
template <class Type>
bool Stack<Type>::push(const Type & item)
{
...
}
如果在类声明中定义了方法(内联定义), 则可以省略模板前缀和类限定符.
模板的具体实现--如:用来处理string对象的栈类被称为实例化(instantiation)或具体化(specialization). 不能将模板成员函数放在独立的实现文件中. 由于模板不是函数, 他们不能单独编译, 模板必须与特定的模板实例化请求一起使用. 因此最简单的方法是将所有模板信息放在一个头文件中, 并在要使用这些模板的肯建中包含该头文件:
看一个完整的例子:
// stacktp.h
#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 & tiem);
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)
{
items[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
使用Stack模板类:
// 创建一个int型的Stack
Stack<int> kernels;
// 创建一个string类型的Stack对象
Stack<string> colonels;
调用模板类的文件:
// 使用Stack模板类
// stacktem.cpp
#include <iostream>
#include <string>
#include <cctype>
#include "stacktp.h"
using std::cin;
using std::cout;
using std::endl;
int main()
{
Stack<std::string> st;
char ch;
std::string po;
cout << "Please enter A to add a purchase order, " << endl;
cout << "P to process a PO, or Q to quit." << endl;
while(cin >> ch && std::toupper(ch) != 'Q')
{
while(cin.get() != '\n')
continue;
if(!std::isalpha(ch))
{
cout << '\a';
continue;
}
switch(ch)
{
case 'A':
case 'a':
cout << "Enter a PO number to add: ";
cin >> po;
if(st.isfull())
cout << "stack already full" << endl;
else
st.push(po);
break;
case 'p':
case 'P':
if(st.isempty())
cout << "stack already empty" << endl;
else {
st.pop(po);
cout << "PO #" << po << " popped" << endl;
}
break;
}
cout << "Please enter A to add a purchase order, P to process a PO, or Q to quit" << endl;
}
cout << "Bye" << endl;
return 0;
}
程序运行结果为: