详解C++编程中的嵌套类的声明与其中的函数使用

可以在一个类的范围内声明另一个类。这样的类称为“嵌套类”。 嵌套类被视为在封闭类的范围内且可在该范围内使用。若要从嵌套类的即时封闭范围之外的某个范围引用该类,则必须使用完全限定名。
下面的示例演示如何声明嵌套类:

// nested_class_declarations.cpp
class BufferedIO
{
public:
  enum IOError { None, Access, General };

  // Declare nested class BufferedInput.
  class BufferedInput
  {
  public:
   int read();
   int good()
   {
     return _inputerror == None;
   }
  private:
    IOError _inputerror;
  };

  // Declare nested class BufferedOutput.
  class BufferedOutput
  {
   // Member list
  };
};

int main()
{
}

在 BufferedIO::BufferedInput 中声明 BufferedIO::BufferedOutput 和 BufferedIO。这些类名称在类 BufferedIO 的范围外不可见。但是,BufferedIO 类型的对象不包含 BufferedInput 或 BufferedOutput 类型的任何对象。
嵌套类只能从封闭类中直接使用名称、类型名称,静态成员的名称和枚举数。若要使用其他类成员的名称,您必须使用指针、引用或对象名。
在前面的 BufferedIO 示例中,枚举 IOError 可由嵌套类中的成员函数、BufferedIO::BufferedInput 或 BufferedIO::BufferedOutput 直接访问,如函数 good 中所示。
注意
嵌套类仅在类范围内声明类型。它们不会导致创建嵌套类的包含对象。前面的示例声明两个嵌套类,但未声明这些类类型的任何对象。
在将类型名称与前向声明一起声明时,会引发嵌套类声明的范围可见性的异常。在这种情况下,由前向声明声明的类名在封闭类的外部可见,其范围定义为最小的封闭非类范围。例如:

// nested_class_declarations_2.cpp
class C
{
public:
  typedef class U u_t; // class U visible outside class C scope
  typedef class V {} v_t; // class V not visible outside class C
};

int main()
{
  // okay, forward declaration used above so file scope is used
  U* pu;

  // error, type name only exists in class C scope
  u_t* pu2; // C2065

  // error, class defined above so class C scope
  V* pv; // C2065

  // okay, fully qualified name
  C::V* pv2;
}

嵌套类中的访问权限
将一个类嵌入另一个类中不会为嵌入类的成员函数提供特殊访问权限。同样,封闭类的成员函数不具有对嵌套类的成员的特殊访问权限。
嵌套类中的成员函数
在嵌套类中声明的成员函数可在文件范围中定义。前面的示例可能已编写:

// member_functions_in_nested_classes.cpp
class BufferedIO
{
public:
  enum IOError { None, Access, General };
  class BufferedInput
  {
  public:
    int read(); // Declare but do not define member
    int good(); // functions read and good.
  private:
    IOError _inputerror;
  };

  class BufferedOutput
  {
    // Member list.
  };
};
// Define member functions read and good in
// file scope.
int BufferedIO::BufferedInput::read()
{
  return(1);
}

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

在前面的示例中,qualified-type-name 语法用于声明函数名称。声明:

BufferedIO::BufferedInput::read()

表示“作为 read 类(位于 BufferedInput 类的范围中)的成员的 BufferedIO 函数。” 由于此声明使用 qualified-type-name 语法,因此以下形式的构造是可能的:

typedef BufferedIO::BufferedInput BIO_INPUT;

int BIO_INPUT::read()

上述声明与前一个声明等效,但它使用了 typedef 名称来代替类名称。
嵌套类中的友元函数
嵌套类中声明的友元函数被认为是在嵌套类而不是封闭类的范围内。因此,友元函数未获得对封闭类的成员或成员函数的特定访问权限。如果需要使用在友元函数中的嵌套类中声明的名称,并且友元函数是在文件范围内定义的,请使用限定的类型名称,如下所示:

// 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; // assign arbitrary value as message number

  strcpy_s( BufferedIO::BufferedInput::message,
       BufferedIO::BufferedInput::messageSize,
       rgszMessage[iMsgNo] );

  return iMsgNo;
}

int main()
{
}

以下代码演示声明为友元函数的函数 GetExtendedErrorStatus。在文件范围内定义的函数中,将消息从静态数组复制到类成员中。请注意,GetExtendedErrorStatus 的更佳实现是将其声明为:

int GetExtendedErrorStatus( char *message )

利用前面的接口,许多类可以通过传递要复制错误消息的内存位置来使用此函数的服务。

(0)

相关推荐

  • C++嵌套类与局部类详细解析

    1. 嵌套类外围类需要使用嵌套类对象作为底层实现,并且该嵌套类只用于外围类的实现,且同时可以对用户隐藏该底层实现.从作用域的角度看,嵌套类被隐藏在外围类之中,该类名只能在外围类中使用.如果在外围类之外的作用域使用该类名时,需要加名字限定. 嵌套类中的成员函数可以在它的类体外定义. 嵌套类的成员函数对外围类的私有成员没有访问权,反之亦然. 嵌套类仅仅只是语法上的嵌入. 2. 局部类类也可以定义在函数体内,这样的类被称为局部类(loacl class).局部类只在定义它的局部域内可见. 局部类的成员

  • 详解C++编程中的嵌套类的声明与其中的函数使用

    可以在一个类的范围内声明另一个类.这样的类称为"嵌套类". 嵌套类被视为在封闭类的范围内且可在该范围内使用.若要从嵌套类的即时封闭范围之外的某个范围引用该类,则必须使用完全限定名. 下面的示例演示如何声明嵌套类: // nested_class_declarations.cpp class BufferedIO { public: enum IOError { None, Access, General }; // Declare nested class BufferedInput.

  • 详解C++编程中的vector类容器用法

    vector简介 vector是STL中最常见的容器,它是一种顺序容器,支持随机访问.vector是一块连续分配的内存,从数据安排的角度来讲,和数组极其相似,不同的地方就是:数组是静态分配空间,一旦分配了空间的大小,就不可再改变了:而vector是动态分配空间,随着元素的不断插入,它会按照自身的一套机制不断扩充自身的容量. vector的扩充机制:按照容器现在容量的一倍进行增长.vector容器分配的是一块连续的内存空间,每次容器的增长,并不是在原有连续的内存空间后再进行简单的叠加,而是重新申请

  • 详解C++编程中的输入输相关的类和对象

    C++输入和输出的概念 我们经常用到的输入和输出,都是以终端为对象的,即从键盘输入数据,运行结果输出到显示器屏幕上.从操作系统的角度看,每一个与主机相连的输入输出设备都被看作一个文件.除了以终端为对象进行输入和输出外,还经常用磁盘(光盘)作为输入输出对象,磁盘文件既可以作为输入文件,也可以作为输出文件. 程序的输入指的是从输入文件将数据传送给程序,程序的输出指的是从程序将数据传送给输出文件. C++输入输出包含以下三个方面的内容: 对系统指定的标准设备的输入和输出.即从键盘输入数据,输出到显示器

  • 详解Python编程中基本的数学计算使用

    数 在 Python 中,对数的规定比较简单,基本在小学数学水平即可理解. 那么,做为零基础学习这,也就从计算小学数学题目开始吧.因为从这里开始,数学的基础知识列位肯定过关了. >>> 3 3 >>> 3333333333333333333333333333333333333333 3333333333333333333333333333333333333333L >>> 3.222222 3.222222 上面显示的是在交互模式下,如果输入 3,就显

  • 详解Java编程中对线程的中断处理

    1. 引言 当我们点击某个杀毒软件的取消按钮来停止查杀病毒时,当我们在控制台敲入quit命令以结束某个后台服务时--都需要通过一个线程去取消另一个线程正在执行的任务.Java没有提供一种安全直接的方法来停止某个线程,但是Java提供了中断机制. 如果对Java中断没有一个全面的了解,可能会误以为被中断的线程将立马退出运行,但事实并非如此.中断机制是如何工作的?捕获或检测到中断后,是抛出InterruptedException还是重设中断状态以及在方法中吞掉中断状态会有什么后果?Thread.st

  • 详解Java编程中包package的内容与包对象的规范

    包的内容 包的内容应该仔细设计,使其只包含在功能上相关的类和接口.包中的类可以自由地访问该包中其他类的非私有成员,有些类甚至可能有足够的权限去访问其他类的内部细节,为了避免这样的类对类成员进行误操作,我们需要对类成员进行保护.任何没有被声明为private的成员都可以被同一个包中的其他所有类型访问,所以任何不相关的类之间的藕合程度都可能会比我们所期望的程度高. 包还为寻找有用的接口和类的程序员提供了逻辑分组的功能.由不相关的类组成的包使程序员很难分辨出哪些接口和类是有用的,而类的逻辑分组可以帮助

  • 详解Java编程中super关键字的用法

    通过用static来定义方法或成员,为我们编程提供了某种便利,从某种程度上可以说它类似于C语言中的全局函数和全局变量.但是,并不是说有了这种便利,你便可以随处使用,如果那样的话,你便需要认真考虑一下自己是否在用面向对象的思想编程,自己的程序是否是面向对象的. 好了,现在开始讨论this&super这两个关键字的意义和用法.在Java中,this通常指当前对象,super则指父类的.当你想要引用当前对象的某种东西,比如当前对象的某个方法,或当前对象的某个成员,你便可以利用this来实现这个目的,当

  • 详解C++编程中的单目运算符重载与双目运算符重载

    C++单目运算符重载 单目运算符只有一个操作数,如!a,-b,&c,*p,还有最常用的++i和--i等.重载单目运算符的方法与重载双目运算符的方法是类似的.但由于单目运算符只有一个操作数,因此运算符重载函数只有一个参数,如果运算符重载函数作为成员函数,则还可省略此参数. 下面以自增运算符"++"为例,介绍单目运算符的重载. [例] 有一个Time类,包含数据成员minute(分)和sec(秒),模拟秒表,每次走一秒,满60秒进一分钟,此时秒又从0开始算.要求输出分和秒的值. #

  • 详解C#编程中构造函数的使用

    当类或结构创建时,其构造函数调用.构造函数与选件类或结构相同,并且,它们通常用于初始化新对象的数据成员. 在下面的示例中,使用一个简单的构造函数定义了名为 Taxi 的类.然后使用 new 运算符来实例化该类.在为新对象分配内存之后,new 运算符立即调用 Taxi 构造函数. public class Taxi { public bool isInitialized; public Taxi() { isInitialized = true; } } class TestTaxi { stat

  • 详解C++编程中的私有继承和公有继承

    C++类的私有继承 在声明一个派生类时将基类的继承方式指定为private的,称为私有继承,用私有继承方式建立的派生类称为私有派生类(private derived class ), 其基类称为私有基类(private base class ). 私有基类的公用成员和保护成员在派生类中的访问属性相当于派生类中的私有成员,即派生类的成员函数能访问它们,而在派生类外不能访问它们.私有基类的私有成员在派生类中成为不可访问的成员,只有基类的成员函数可以引用它们.一个基类成员在基类中的访问属性和在派生类中

随机推荐