Nested classes (C++ only)

5992 ワード

access rules and nested classesThe following example (adapted from standard, section 11.8.1)
class E
{
int x;
class I
{
void f(E* p, int i)
{
p->x = i;//error
}
};
};
is illegal because nested class I has no special access to enclosing class
E. E::x is private and therefore p->x is an access error.
Yet Comeau C++, gcc 3.2 and Visual C++ 7.1 all compile it. What is going on?
Has the standard changed recently?
john
A:It is a bug in these compilers. HP's aCC compiler gives the expected error.
The other vendors are being milder.
B:Actually I found this
http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/cwg_defects.html#45
the standard is going to change in this regard. I guess gcc, Comeau and VC++
are anticipating the change while aCC is not.
John
Nested classes (C++ only)
A nested class is declared within the scope of another class. The name of a nested class is local to its enclosing class. Unless you use explicit pointers, references, or object names, declarations in a nested class can only use visible constructs, including type names, static members, and enumerators from the enclosing class and global variables.
Member functions of a nested class follow regular access rules and have no special access privileges to members of their enclosing classes. Member functions of the enclosing class have no special access to members of a nested class. The following example demonstrates this:
class A {
int x;

class B { };

class C {

// The compiler cannot allow the following
// declaration because A::B is private:
// B b;

int y;
void f(A* p, int i) {

// The compiler cannot allow the following
// statement because A::x is private:
// p->x = i;

}
};

void g(C* p) {

// The compiler cannot allow the following
// statement because C::y is private:
// int z = p->y;
}
};

int main() { }

The compiler would not allow the declaration of object b because class A::B is private. The compiler would not allow the statement p->x = i because A::x is private. The compiler would not allow the statement int z = p->y because C::y is private.
You can define member functions and static data members of a nested class in namespace scope. For example, in the following code fragment, you can access the static members x and y and member functions f() and g() of the nested class nested by using a qualified type name. Qualified type names allow you to define a typedef to represent a qualified class name. You can then use the typedef with the::(scope resolution) operator to refer to a nested class or class member, as shown in the following example:
class outside
{
public:
class nested
{
public:
static int x;
static int y;
int f();
int g();
};
};
int outside::nested::x = 5;
int outside::nested::f() { return 0; };

typedef outside::nested outnest; // define a typedef
int outnest::y = 10; // use typedef with ::
int outnest::g() { return 0; };

However, using a typedef to represent a nested class name hides information and may make the code harder to understand.
You cannot use a typedef name in an elaborated type specifier. To illustrate, you cannot use the following declaration in the above example:
  class outnest obj;

A nested class may inherit from private members of its enclosing class. The following example demonstrates this:
class A {
private:
class B { };
B *z;

class C : private B {
private:
B y;
// A::B y2;
C *x;
// A::C *x2;
};
};

The nested class A::C inherits from A::B. The compiler does not allow the declarations A::B y2 and A::C *x2 because both A::B and A::C are private.
9.7 Nested class declarations1 A class can be defined within another class. A class defined within another is called a nested class. Thename of a nested class is local to its enclosing class. The nested class is in the scope of its enclosing class.Except by using explicit pointers, references, and object names, declarations in a nested class can use onlytype names, static members, and enumerators from the enclosing class. [Example:int x;int y;class enclose {public:int x;static int s;class inner {void f(int i){int a = sizeof(x);//error: refers to enclose::xx = i;//error: assign to enclose::xs = i;//OK: assign to enclose::s::x = i;//OK: assign to global xy = i;//OK: assign to global y}void g(enclose* p, int i){p->x = i;//OK: assign to enclose::x}};};inner* p = 0;//error: inner not in scope—end example]2 Member functions and static data members of a nested class can be defined in a namespace scope enclosingthe definition of their class. [Example:
class enclose {public:class inner {static int x;void f(int i);};};int enclose::inner::x = 1;void enclose::inner::f(int i) {/* ... */}—end example]3 If class X is defined in a namespace scope, a nested class Y may be declared in class X and later defined inthe definition of class X or be later defined in a namespace scope enclosing the definition of class X.[Example:class E {class I1;//forward declaration of nested classclass I2;class I1 {};//definition of nested class};class E::I2 {};//definition of nested class—end example]4 Like a member function, a friend function (11.4) defined within a nested class is in the lexical scope of thatclass; it obeys the same rules for name binding as a static member function of that class (9.4) and has nospecial access rights to members of an enclosing class.