详解C++编程中的嵌套类的声明与其中的函数使用
可以在一个类的范围内声明另一个类。这样的类称为“嵌套类”。嵌套类被视为在封闭类的范围内且可在该范围内使用。若要从嵌套类的即时封闭范围之外的某个范围引用该类,则必须使用完全限定名。
下面的示例演示如何声明嵌套类:
//nested_class_declarations.cpp classBufferedIO { public: enumIOError{None,Access,General}; //DeclarenestedclassBufferedInput. classBufferedInput { public: intread(); intgood() { return_inputerror==None; } private: IOError_inputerror; }; //DeclarenestedclassBufferedOutput. classBufferedOutput { //Memberlist }; }; intmain() { }
在BufferedIO::BufferedInput中声明BufferedIO::BufferedOutput和BufferedIO。这些类名称在类BufferedIO的范围外不可见。但是,BufferedIO类型的对象不包含BufferedInput或BufferedOutput类型的任何对象。
嵌套类只能从封闭类中直接使用名称、类型名称,静态成员的名称和枚举数。若要使用其他类成员的名称,您必须使用指针、引用或对象名。
在前面的BufferedIO示例中,枚举IOError可由嵌套类中的成员函数、BufferedIO::BufferedInput或BufferedIO::BufferedOutput直接访问,如函数good中所示。
注意
嵌套类仅在类范围内声明类型。它们不会导致创建嵌套类的包含对象。前面的示例声明两个嵌套类,但未声明这些类类型的任何对象。
在将类型名称与前向声明一起声明时,会引发嵌套类声明的范围可见性的异常。在这种情况下,由前向声明声明的类名在封闭类的外部可见,其范围定义为最小的封闭非类范围。例如:
//nested_class_declarations_2.cpp classC { public: typedefclassUu_t;//classUvisibleoutsideclassCscope typedefclassV{}v_t;//classVnotvisibleoutsideclassC }; intmain() { //okay,forwarddeclarationusedabovesofilescopeisused U*pu; //error,typenameonlyexistsinclassCscope u_t*pu2;//C2065 //error,classdefinedabovesoclassCscope V*pv;//C2065 //okay,fullyqualifiedname C::V*pv2; }
嵌套类中的访问权限
将一个类嵌入另一个类中不会为嵌入类的成员函数提供特殊访问权限。同样,封闭类的成员函数不具有对嵌套类的成员的特殊访问权限。
嵌套类中的成员函数
在嵌套类中声明的成员函数可在文件范围中定义。前面的示例可能已编写:
//member_functions_in_nested_classes.cpp classBufferedIO { public: enumIOError{None,Access,General}; classBufferedInput { public: intread();//Declarebutdonotdefinemember intgood();//functionsreadandgood. private: IOError_inputerror; }; classBufferedOutput { //Memberlist. }; }; //Definememberfunctionsreadandgoodin //filescope. intBufferedIO::BufferedInput::read() { return(1); } intBufferedIO::BufferedInput::good() { return_inputerror==None; } intmain() { }
在前面的示例中,qualified-type-name语法用于声明函数名称。声明:
BufferedIO::BufferedInput::read()
表示“作为read类(位于BufferedInput类的范围中)的成员的BufferedIO函数。”由于此声明使用qualified-type-name语法,因此以下形式的构造是可能的:
typedefBufferedIO::BufferedInputBIO_INPUT; intBIO_INPUT::read()
上述声明与前一个声明等效,但它使用了typedef名称来代替类名称。
嵌套类中的友元函数
嵌套类中声明的友元函数被认为是在嵌套类而不是封闭类的范围内。因此,友元函数未获得对封闭类的成员或成员函数的特定访问权限。如果需要使用在友元函数中的嵌套类中声明的名称,并且友元函数是在文件范围内定义的,请使用限定的类型名称,如下所示:
//friend_functions_and_nested_classes.cpp #include<string.h> enum { sizeOfMessage=255 }; char*rgszMessage[sizeOfMessage]; classBufferedIO { public: classBufferedInput { public: friendintGetExtendedErrorStatus(); staticchar*message; staticintmessageSize; intiMsgNo; }; }; char*BufferedIO::BufferedInput::message; intBufferedIO::BufferedInput::messageSize; intGetExtendedErrorStatus() { intiMsgNo=1;//assignarbitraryvalueasmessagenumber strcpy_s(BufferedIO::BufferedInput::message, BufferedIO::BufferedInput::messageSize, rgszMessage[iMsgNo]); returniMsgNo; } intmain() { }
以下代码演示声明为友元函数的函数GetExtendedErrorStatus。在文件范围内定义的函数中,将消息从静态数组复制到类成员中。请注意,GetExtendedErrorStatus的更佳实现是将其声明为:
intGetExtendedErrorStatus(char*message)
利用前面的接口,许多类可以通过传递要复制错误消息的内存位置来使用此函数的服务。