Making a structure nested doesn’t automatically give it access to private members. To accomplish this, you must follow a particular form: first, declare (without defining) the nested structure, then declare it as a friend, and finally define the structure. The structure definition must be separate from the friend declaration, otherwise it would be seen by the compiler as a non-member.
But cpp annotations says :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
class Surround
{
// class SecondWithin; not required: friend declarations (see
// below) double as forward declarations
staticint s_variable;
public:
class FirstWithin
{
friendclass Surround;
friendclass SecondWithin;
...
...
struct enclosing
{
struct nested_three ; // declaration of class enclosing::nested_three
struct nested_one
{
// A nested class is a member and as such has the same access rights as any other member. - IS
void foo( enclosing& outer ) { ++outer.i ; }
// note: therefore, enclosing::nested_one::foo is implicitly a friend of enclosing
// note: a friend declaration is not required
private: int j = 22 ;
// The members of an enclosing class have no special access to members of a nested class;
// the usual access rules shall be obeyed. - IS
friend enclosing ; // enclosing declared to be a friend of enclosing::nested_one
// A name nominated by a friend declaration shall be accessible
// in the scope of the class containing the friend declaration. - IS
// friend nested_two ; // *** error: the name nested_two hasn't been seen
friendclass nested_two ; // fine; declares class enclosing::nested_two to be a friend
// note: here, 'the scope of the class containing the friend declaration' is the scope of the class enclosing
// note: therefore, this declares enclosing::nested_two to be a friend class
friend nested_three ; // fine; there was a declaration of class enclosing::nested_three
};
void bar( nested_one& n1 ) { ++n1.j ; } // ok, enclosing is a friend of enclosing::nested_one
struct nested_two
{
// A nested class is a member and as such has the same access rights as any other member. - IS
void baz2( enclosing& outer ) { ++outer.i ; }
void foobar2( nested_one& n1 ) { ++n1.j ; } // ok, enclosing::nested_two is a friend of enclosing::nested_one
};
struct nested_three
{
// A nested class is a member and as such has the same access rights as any other member. - IS
void baz3( enclosing& outer ) { ++outer.i ; }
void foobar3( nested_one& n1 ) { ++n1.j ; } // ok, enclosing::nested_three is a friend of enclosing::nested_one
};
private: int i = 8 ;
};
EDIT: To clear any ambiguity: What 'Thinking in c++' said was correct at the time the book was written. In legacy C++, members of a nested class had unrestricted access to only these in the enclosing class: types, static members and enumerators.