Are inner classes in C++ automatically friends?

If I define an inner class in C++, is it automatically a friend of the class that contains it? For example, is this legal:

class Outer {
public:
class Inner {
public:
void mutateOuter(Outer& o);
};


private:
int value;
};


void Outer::Inner::mutateOuter(Outer& o) {
o.value ++; // Legal?  Or not?
}

I ask because on some compilers I've tried (VS2003) this code won't work, but I've heard at least anecdotally that it does work on some compilers. I can't find a relevant section in the C++ spec about this, and if anyone can cite something specific that would say that it is or is not legal that would be great.

25485 次浏览

Until C++11 (i.e C++98 and C++03)

In C++98 and C++03, nested class cannot access private and protected members of enclosing class by default.

The C++ Standard (2003) says in $11.8/1 [class.access.nest],

The members of a nested class have no special access to members of an enclosing class, nor to classes or functions that have granted friendship to an enclosing class; the usual access rules (clause 11) shall be obeyed. The members of an enclosing class have no special access to members of a nested class; the usual access rules (clause 11) shall be obeyed.

Example from the Standard itself:

class E
{
int x;
class B { };
class I
{
B b; // error: E::B is private
int y;
void f(E* p, int i)
{
p->x = i; // error: E::x is private
}
};
int g(I* p)
{
return p->y; // error: I::y is private
}
};

Since C++11

The above restriction has been removed since C++11. Now the nested classes can access the private and protected members of the enclosing class:

class E
{
int x;
class B { };
class I
{
B b; // ok: even though E::B is private
int y;
void f(E* p, int i)
{
p->x = i; // ok: even though E::x is private
}
};
int g(I* p)
{
return p->y; // ok: even though I::y is private
}
};

Hope that helps.

I don't the precise location off the top of my head, but I do recall reading through the specs and finding that any private data in a class is hidden from all other classes, including nested classes.

Basically, nesting a class defines a certain scope, not access priviledges.

This answer pertains to the (outdated) C++03 specification. The accepted answer at this question is more up to date.

Well, I feel silly for asking this question now because I just found the relevant part of the spec that covers this: §11.8/1:

The members of a nested class have no special access to members of an enclosing class, nor to classes or functions that have granted friendship to an enclosing class; the usual access rules (clause 11) shall be obeyed. The members of an enclosing class have no special access to members of a nested class; the usual access rules (clause 11) shall be obeyed

(My emphasis)

So it looks like no, inner classes do not have special access privileges.

Since the questioner seems to have accepted one of the answer, this is just a supplementation.
The standard seems to have changed the specification about the accessibility.

§11.8/1 in C++98 states:

The members of a nested class have no special access to members of an enclosing class, nor to classes or functions that have granted friendship to an enclosing class; the usual access rules shall be obeyed.

§11.8/1 in N1804(after TR1) states:

A nested class is a member and as such has the same access rights as any other member.

I think current C++ compilers obey newer specification.

After having asked more or less the same question here myself, I wanted to share the (apparently) updated answer for C++11:

Quoted from https://stackoverflow.com/a/14759027/1984137:

standard $11.7.1

"A nested class is a member and as such has the same access rights as any other member. The members of an enclosing class have no special access to members of a nested class; the usual access rules shall be obeyed"

and the usual access rules specify that:

"A member of a class can also access all the names to which the class has access..."

specific examples has been given in the standard:

class E {
int x;
class B { };


class I {
B b; // OK: E::I can access E::B
int y;
void f(E* p, int i) {
p->x = i; // OK: E::I can access E::x
}
};
}