85

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.

GEOCHET
  • 21,119
  • 15
  • 74
  • 98
templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
  • Member functions of a nested class follow regular access rules and have no special access privileges to members of their enclosing classes.: http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Fcplr061.htm – Anycorn Feb 16 '11 at 07:39
  • 1
    @aaa- Thanks for the link, but this seems to only apply to IBM's compiler, which I know does take a few liberties with the spec (for example, allowing you to take the address of a label with the `&&` operator). Sorry if I'm being a stickler on this one, but I teach a C++ programming course and want to be very certain of the answer before I tell anything to my students. – templatetypedef Feb 16 '11 at 07:40
  • I don't think so because if that was the case then we would not explicitly need to declare friend classes also within the class body. Just a declaration should suffice in that case – mukeshkumar Feb 16 '11 at 07:41
  • @template AFAIK they specifically list non-standard extensions. – Anycorn Feb 16 '11 at 07:41
  • 4
    By the way, the question is not "is it a friend", but "does it have private access". (The former is sufficient, but not necessary.) – GManNickG Feb 16 '11 at 07:47
  • @GMan- You're absolutely right. Thanks for pointing that out! – templatetypedef Feb 16 '11 at 07:47
  • See [DR 45](http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#45). – Fred Nurk Feb 16 '11 at 08:06
  • The standard has been revised, hence the either the accepted answer should be corrected or the [correct answer](http://stackoverflow.com/a/14759603/514235) should be revised. – iammilind Jul 16 '15 at 06:37

5 Answers5

82

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
        }
    };
}
Community
  • 1
  • 1
hcc23
  • 1,180
  • 11
  • 17
  • 2
    Fully agree. I think, the answer for this question should be revised, since the code presented in the question can compile correctly now. Here is the proof: [link](http://ideone.com/uSfXnZ) – Givi Nov 13 '13 at 11:17
  • gcc 4.8.2 has a bug which was only fixed in gcc 4.9.0. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59482 – Paulo Neves Jun 08 '14 at 19:11
  • In short: yes for C++11 and onwards, but no for C++03 and backwards. – Daniel Kiss Feb 09 '17 at 18:40
54

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

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: Yes.

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.

einpoklum
  • 118,144
  • 57
  • 340
  • 684
Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • @templatetypedef: I knew that nested class cannot access private members of enclosing class, but quoted the wrong reference. Anyway I corrected the reference! – Nawaz Feb 16 '11 at 07:56
  • 2
    After omitting `g()`, the code [compiles fine](http://ideone.com/suW6IO) with C++11 onwards. Should update answer. – iammilind Jul 16 '15 at 06:36
  • 1
    I tried compiling this code on xcode 9.2 using its default compiler (LLVM 9.0), and it did not compile. It fails at the line **return p->y**. It seems that accessing the parent class private members is okay, but accessing the children class private members from the parent class is not ok. – Rafael Sabino Feb 21 '18 at 15:58
16

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.

Ise Wisteria
  • 11,259
  • 2
  • 43
  • 26
  • 2
    A nested class is a member, but can nested class members be considered to be members of the enclosing class? It isn't obvious. The nested class itself (not its members) can access members of the enclosing class like this: `class Enclosing {private: enum PrivateEnum {VALUE}; class Nested {/*accessing enclosing class' member type*/ PrivateEnum e;}; };`. – Sergei Tachenov Feb 16 '11 at 10:18
  • 1
    @SergeyTachenov: Hi. §11.8/1 in N1804 also states: _The members of an enclosing class have no special access to members of a nested class_; _the usual access rules shall be obeyed._ This statement didn't change from C++98. So, as for the access from enclosing class to nested class(the opposite of templatetypedef's question), the usual access rules apply. – Ise Wisteria Feb 16 '11 at 11:50
  • @Ise, I'm not talking about access to members of a nested class, it's an entirely different issue. I'm just not sure if the "a nested class is a member" concept applies to the members of the nested class too. What about several levels of nesting then? – Sergei Tachenov Feb 16 '11 at 13:39
  • @SergeyTachenov: Sorry, I misunderstood your comment. If you mean whether `class A { int i; class B { struct C { void f( A* x ) { x->i = 0; } }; }; };` is allowed in the standard, I suppose allowing it is the standard's intent. VC8, g++3.4.5 and Comeau online allow it. But I cannot say definite thing. If you are concerned, I'd recommend to post that question in StackOverflow. Someone with more detailed knowledge than me will answer. – Ise Wisteria Feb 16 '11 at 14:24
  • @Ise, sorry for putting irrelevant stuff in. Initially I was commenting on the quote from N1804: "A nested class is a member" - does this imply that members of the nested class are members of the enclosing class too? I mean, in `class A {int i; class B {A *a; int f() {return a->i;} }; };` the class B is a member of the class A, but B::f() is a member of the class A::B, not A! But I've just found another quote from DR 45 that might clarify this: "A member of a class can also access all names as the class of which it is a member." In other words, B::f() "inherits" access right of the class B. – Sergei Tachenov Feb 16 '11 at 17:12
  • @SergeyTachenov: I think your inference is right. The relationship between enclosing class and nested class is transitive probably. `class A {int i; class B {A *a; int f() {return a->i;} }; };` VC8, g++3.4.5, ideone(gcc4.3.4) and Comeau online accept your above code :-) – Ise Wisteria Feb 16 '11 at 17:33
4

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.

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
3

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.

Ken Wayne VanderLinde
  • 18,915
  • 3
  • 47
  • 72
  • 1
    You're incorrect, but I'm only -1'ing because somehow, even with the quoted correct answer nearby, this got +1'd. @Voters, please read all the answers before you go voting willy-nilly. – GManNickG Feb 16 '11 at 07:50