当前位置:嗨网首页>书籍在线阅读

16-定义类模板

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

14.4.1 定义类模板

下面以第10章的Stack类为基础来建立模板。原来的类声明如下:

typedef unsigned long Item;
class Stack
{
private:
    enum {MAX = 10}; // constant specific to class
    Item items[MAX]; // holds stack items
    int top;         // index for top stack item
public:
    Stack();
    bool isempty() const;
    bool isfull() const;
    // push() returns false if stack already is full, true otherwise
    bool push(const Item & item); // add item to stack
    // pop() returns false if stack already is empty, true otherwise
    bool pop(Item & item);        // pop top into item
};

采用模板时,将使用模板定义替换Stack声明,使用模板成员函数替换Stack的成员函数。和模板函数一样,模板类以下面这样的代码开头:

template <class Type>

关键字template告诉编译器,将要定义一个模板。尖括号中的内容相当于函数的参数列表。可以把关键字class看作是变量的类型名,该变量接受类型作为其值,把Type看作是该变量的名称。

这里使用class并不意味着Type必须是一个类;而只是表明Type是一个通用的类型说明符,在使用模板时,将使用实际的类型替换它。较新的C++实现允许在这种情况下使用不太容易混淆的关键字typename代替class:

template <typename Type> // newer choice

可以使用自己的泛型名代替Type,其命名规则与其他标识符相同。当前流行的选项包括T和Type,我们将使用后者。当模板被调用时,Type将被具体的类型值(如int或string)取代。在模板定义中,可以使用泛型名来标识要存储在栈中的类型。对于Stack来说,这意味着应将声明中所有的typedef标识符Item替换为Type。例如,

Item items[MAX]; // holds stack items

应改为:

Type items[MAX]; // holds stack items

同样,可以使用模板成员函数替换原有类的类方法。每个函数头都将以相同的模板声明打头:

template <class Type>

同样应使用泛型名Type替换typedef标识符Item。另外,还需将类限定符从Stack::改为Stack::。例如,

bool Stack::push(const Item & item)
{
...
}

应该为:

template <class Type> // or template <typename Type>
bool Stack<Type>::push(const Type & item)
{
...
}

如果在类声明中定义了方法(内联定义),则可以省略模板前缀和类限定符。

程序清单14.13列出了类模板和成员函数模板。知道这些模板不是类和成员函数定义至关重要。它们是C++编译器指令,说明了如何生成类和成员函数定义。模板的具体实现——如用来处理string对象的栈类——被称为实例化(instantiation)或具体化(specialization)。不能将模板成员函数放在独立的实现文件中(以前,C++标准确实提供了关键字export,让您能够将模板成员函数放在独立的实现文件中,但支持该关键字的编译器不多;C++11不再这样使用关键字export,而将其保留用于其他用途)。由于模板不是函数,它们不能单独编译。模板必须与特定的模板实例化请求一起使用。为此,最简单的方法是将所有模板信息放在一个头文件中,并在要使用这些模板的文件中包含该头文件。

程序清单14.13 stacktp.h

// stacktp.h -- a stack template
#ifndef STACKTP_H_
#define STACKTP_H_
template <class Type>
class Stack
{
private:
    enum {MAX = 10}; // constant specific to class
    Type items[MAX]; // holds stack items
    int top;           // index for top stack item
public:
    Stack();
    bool isempty();
    bool isfull();
    bool push(const Type & item); // add item to stack
    bool pop(Type & item); // pop top into 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