曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 3705|回复: 0
打印 上一主题 下一主题

嵌套类

[复制链接]

716

主题

734

帖子

2946

积分

超级版主

Rank: 9Rank: 9Rank: 9

积分
2946
跳转到指定楼层
楼主
发表于 2013-12-27 17:55:33 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
一个类可以在另一个类中声明,这个类就称为“嵌套类”(nested class),它通过提供新的类型类作用域来避免名称混乱,而包含嵌套类的类称为“包含类”(enclosing class)。

包含类的成员函数可以创建和使用嵌套类的对象,而仅当声明位于公有部分,才能在包含类的外面使用嵌套类,并且必须使用作用域解析运算符。

下面的例子展示了如何声明嵌套类:
[C++] 纯文本查看 复制代码
// nested_class_declarations.cpp
class BufferedIO
{
public:
   enum IOError { None, Access, General };

   // 声明嵌套类 BufferedInput.
   class BufferedInput
   {
   public:
      int read();
      int good()
      {
         return _inputerror == None;
      }
   private:
       IOError _inputerror;
   };

   // 声明嵌套类 BufferedOutput.
   class BufferedOutput
   {
      // 成员列表
   };
};

int main()
{
}

在上面,BufferedIO::BufferedInput 和 BufferedIO::BufferedOutput 在 BufferedIO 里声明。那么,BufferedInput 和 BufferedOutput 在外部是不可见的,即不能在 main() 函数里直接用它来声明一个对象,比如 BufferedInput myinput; 和 BufferedOutput myoutput; 是错误的。但是,像在上面的代码中,这两个嵌套类位于包含类的共有部分,因此可以用作用域限定符来在 main() 中声明对象,比如:
  1. int main()
  2. {
  3.     BufferedIO::BufferedInput myinput;
  4.     BufferedIO::BufferedOutput myoutput;
  5. }
复制代码
然而,如果两个嵌套类位于私有部分,像上面那么做又是不允许的。这实际上和普通的成员的权限关系是一致的:
如果嵌套类是在包含类的私有部分声明的,则只有后者知道它;对于从包含类派生出来的类,嵌套类也是不可见的,因为派生类不能直接访问基类的私有部分。
如果嵌套类是在包含类的保护部分声明的,则对于后者来说是可见的,但是对于外部世界则是不可见的。但是派生类将知道嵌套类,并可以直接创建这种类型的对象。
如果嵌套类是在包含类的公有部分声明的,则允许后者、后者的派生类以及外部世界使用它。由于嵌套类的作用域为包含它的类,因此在外部世界使用它时,必须使用类限定符,如上 main() 函数所示。


嵌套类仅可以直接使用包含类中的类型名,静态成员名,以及枚举量。如上 BufferedIO 这个例子所示,枚举量 IOError可以直接被嵌套类中的成员函数访问。

看一种特殊的情况:当一个嵌套类被前向声明的时候,它可以在包含类的外面可见。考虑下面的代码:
[C++] 纯文本查看 复制代码
class C
{
public:
	typedef class U u_t; // 类 U 在类 C 的外部可见(这里类 U 是一种前向声明)
	typedef class V {} v_t; // 类 V 在类 C 外不可见,注意 V 后面有一对大括号,表示类 V 已经被定义
};

int main()
{
	// 正确,因为有了上面的前向声明,所以这里可以使用
	U* pu;

	// 错误,类型名只存在于类 C 的作用域中
	u_t* pu2; // C2065

	// 错误,V 被定义在类 C 中
	V* pv; // C2065

	// 正确,因为是全限定形式
	C::V* pv2;
}


嵌套类中的成员函数
嵌套类中声明的成员函数可以在文件作用域里定义,考虑下面代码:
[C++] 纯文本查看 复制代码
// member_functions_in_nested_classes.cpp
class BufferedIO
{
public:
    enum IOError { None, Access, General };
    class BufferedInput
    {
    public:
        int read(); // 声明,但没有定义
        int good(); // 声明,但没有定义
    private:
        IOError _inputerror;
    };

    class BufferedOutput
    {
        // 成员列表
    };
};
// 在文件作用域中定义 read() 和 good()
int BufferedIO::BufferedInput::read()
{
   return(1);
}

int BufferedIO::BufferedInput::good()
{
    return _inputerror == None;
}
int main()
{
}

在上面的代码中,注意定义函数时使用的是“限定类型名”(qualified-type-name) 语法:
  1. BufferedIO::BufferedInput::read()
复制代码
这意味着,read() 函数是 BufferedIO 类中的 BufferedInput 类的成员。也可以利用 typedef 来缩短该定义:

  1. typedef BufferedIO::BufferedInput BIO_INPUT;int BIO_INPUT::read()
复制代码
嵌套类与友元函数
在嵌套类中声明的友元函数的作用域仅在嵌套类中,而不能作用于包含类。因此,友元函数并没有什么特殊访问包含类成员或成员函数的权限。如果你想让嵌套类的友元函数(该函数定义在文件作用域中)中使用一个嵌套类中的名称,
那么需要使用限制类型名称。如下代码所示:
[C++] 纯文本查看 复制代码
// friend_functions_and_nested_classes.cpp

#include <string.h>

enum
{
    sizeOfMessage = 255
};

char *rgszMessage[sizeOfMessage];

class BufferedIO
{
public:
    class BufferedInput
    {
    public:
        friend int GetExtendedErrorStatus();
        static char *message;
        static int  messageSize;
        int iMsgNo;
   };
};

char *BufferedIO::BufferedInput::message;
int BufferedIO::BufferedInput::messageSize;

//友元函数定义在文件作用域中
int GetExtendedErrorStatus()
{
    int iMsgNo = 1; 

//使用限定语法
    strcpy_s( BufferedIO::BufferedInput::message,
              BufferedIO::BufferedInput::messageSize,
              rgszMessage[iMsgNo] );

    return iMsgNo;
}

int main()
{
}


您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2024-4-30 12:06 , Processed in 0.066832 second(s), 23 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表