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

07-嵌套类

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

15.2 嵌套类

在C++中,可以将类声明放在另一个类中。在另一个类中声明的类被称为嵌套类(nested class),它通过提供新的类型类作用域来避免名称混乱。包含类的成员函数可以创建和使用被嵌套类的对象;而仅当声明位于公有部分,才能在包含类的外面使用嵌套类,而且必须使用作用域解析运算符(然而,旧版本的C++不允许嵌套类或无法完全实现这种概念)。

对类进行嵌套与包含并不同。包含意味着将类对象作为另一个类的成员,而对类进行嵌套不创建类成员,而是定义了一种类型,该类型仅在包含嵌套类声明的类中有效。

对类进行嵌套通常是为了帮助实现另一个类,并避免名称冲突。Queue类示例(第12章的程序清单12.8)嵌套了结构定义,从而实现了一种变相的嵌套类:

class Queue
{
private:
// class scope definitions
    // Node is a nested structure definition local to this class
    struct Node {Item item; struct Node * next;};
    ...
};

由于结构是一种其成员在默认情况下为公有的类,所以Node实际上是一个嵌套类,但该定义并没有充分利用类的功能。具体地说,它没有显式构造函数,下面进行补救。

首先,找到Queue示例中创建Node对象的位置。从类声明(程序清单11.10)和方法定义(程序清单12.11)可知,唯一创建了Node对象的地方是enqueue()方法:

bool Queue::enqueue(const Item & item)
{
    if (isfull())
        return false;
    Node * add = new Node; // create node
// on failure, new throws std::bad_alloc exception
    add->item = item;      // set node pointers
    add->next = NULL;
    ...
}

上述代码创建Node后,显式地给Node成员赋值,这种工作更适合由构造函数来完成。

知道应在什么地方以及如何使用构造函数后,便可以提供一个适当的构造函数定义:

class Queue
{
// class scope definitions
    // Node is a nested class definition local to this class
    class Node
    {
    public:
        Item item;
        Node * next;
        Node(const Item & i) : item(i), next(0) { }
    };
    ...
};

该构造函数将节点的item成员初始化为i,并将next指针设置为0,这是使用C++编写空值指针的方法之一(使用NULL时,必须包含一个定义NULL的头文件;如果您使用的编译器支持C++11,可使用nullptr)。由于使用Queue类创建的所有节点的next的初始值都被设置为空指针,因此这个类只需要该构造函数。

接下来,需要使用构造函数重新编写enqueue():

bool Queue::enqueue(const Item & item)
{
    if (isfull())
        return false;
    Node * add = new Node(item); // create, initialize node
// on failure, new throws std::bad_alloc exception
    ...
}

这使得enqueue()的代码更短,也更安全,因为它自动进行初始化,无需程序员记住应做什么。

这个例子在类声明中定义了构造函数。假设想在方法文件中定义构造函数,则定义必须指出Node类是在Queue类中定义的。这是通过使用两次作用域解析运算符来完成的:

Queue::Node::Node(const Item & i) : item(i), next(0) { }