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

09-模板中的嵌套

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

15.2.2 模板中的嵌套

您知道,模板很适合用于实现诸如Queue等容器类。您可能会问,将Queue类定义转换为模板时,是否会由于它包含嵌套类而带来问题?答案是不会。程序清单15.5演示了如何进行这种转换。和类模板一样,该头文件也包含类模板和方法函数模板。

程序清单15.5 queuetp.h

// queuetp.h -- queue template with a nested class
#ifndef QUEUETP_H_
#define QUEUETP_H_
template <class Item>
class QueueTP
{
private:
    enum {Q_SIZE = 10};
    // Node is a nested class definition
    class Node
    {
    public:
        Item item;
        Node * next;
        Node(const Item & i):item(i), next(0){ }
    };
    Node * front;     // pointer to front of Queue
    Node * rear;      // pointer to rear of Queue
    int items;        // current number of items in Queue
    const int qsize; // maximum number of items in Queue
    QueueTP(const QueueTP & q) : qsize(0) {}
    QueueTP & operator=(const QueueTP & q) { return *this; }
public:
    QueueTP(int qs = Q_SIZE);
    ~QueueTP();
    bool isempty() const
    {
        return items == 0;
    }
    bool isfull() const
    {
        return items == qsize;
    }
    int queuecount() const
    {
        return items;
    }
    bool enqueue(const Item &item); // add item to end
    bool dequeue(Item &item); // remove item from front
};
// QueueTP methods
template <class Item>
QueueTP<Item>::QueueTP(int qs) : qsize(qs)
{
    front = rear = 0;
    items = 0;
}
template <class Item>
QueueTP<Item>::~QueueTP()
{
    Node * temp;
    while (front != 0) // while queue is not yet empty
    {
        temp = front;  // save address of front item
        front = front->next;// reset pointer to next item
        delete temp;   // delete former front
    }
}
// Add item to queue
template <class Item>
bool QueueTP<Item>::enqueue(const Item & item)
{
    if (isfull())
        return false;
    Node * add = new Node(item); // create node
// on failure, new throws std::bad_alloc exception
    items++;
    if (front == 0)       // if queue is empty,
        front = add;      // place item at front
    else
        rear->next = add; // else place at rear
    rear = add;           // have rear point to new node
    return true;
}
// Place front item into item variable and remove from queue
template <class Item>
bool QueueTP<Item>::dequeue(Item & item)
{
    if (front == 0)
        return false;
    item = front->item;  // set item to first item in queue
    items--;
    Node * temp = front; // save location of first item
    front = front->next; // reset front to next item
    delete temp;         // delete former first item
    if (items == 0)
        rear = 0;
    return true;
}
#endif

程序清单15.5中模板有趣的一点是,Node是利用通用类型Item来定义的。所以,下面的声明将导致Node被定义成用于存储double值:

QueueTp<double> dq;

而下面的声明将导致Node被定义成用于存储char值:

QueueTp<char> cq;

这两个Node类将在两个独立的QueueTP类中定义,因此不会发生名称冲突。即一个节点的类型为QueueTP::Node,另一个节点的类型为QueueTP::Node。

程序清单15.6是一个小程序,可用于测试这个新的类。

程序清单15.6 nested.cpp

// nested.cpp -- using a queue that has a nested class
#include <iostream>
#include <string>
#include "queuetp.h"
int main()
{
    using std::string;
    using std::cin;
    using std::cout;
    QueueTP<string> cs(5);
    string temp;
    while(!cs.isfull())
    {
        cout << "Please enter your name. You will be "
                "served in the order of arrival.\n"
                "name: ";
    getline(cin, temp);
    cs.enqueue(temp);
    }
    cout << "The queue is full. Processing begins!\n";
    while (!cs.isempty())
    {
        cs.dequeue(temp);
        cout << "Now processing " << temp << "...\n";
    }
    return 0;
}

程序清单15.5和程序清单15.6组成的程序的运行情况如下:

Please enter your name. You will be served in the order of arrival.
name: Kinsey Millhone
Please enter your name. You will be served in the order of arrival.
name: Adam Dalgliesh
Please enter your name. You will be served in the order of arrival.
name: Andrew Dalziel
Please enter your name. You will be served in the order of arrival.
name: Kay Scarpetta
Please enter your name. You will be served in the order of arrival.
name: Richard Jury
The queue is full. Processing begins!
Now processing Kinsey Millhone...
Now processing Adam Dalgliesh...
Now processing Andrew Dalziel...
Now processing Kay Scarpetta...
Now processing Richard Jury...