Friend scope (C++ only)

The name of a friend function or class first introduced in a friend declaration is not in the scope of the class granting friendship (also called the enclosing class) and is not a member of the class granting friendship.

The name of a function first introduced in a friend declaration is in the scope of the first nonclass scope that contains the enclosing class. The body of a function provided inside a friend declaration is handled in the same way as a member function defined within a class. Processing of the definition does not start until the end of the outermost enclosing class. In addition, unqualified names in the body of the function definition are searched for starting from the class containing the function definition.

A friend class name first introduced by a friend declaration is considered to belong to the first nonclass enclosing scope. Until a matching declaration is provided in that scope, the class name is not found by name lookup. For example:
namespace A {    //the first nonclass scope
   class B {
        class C { 
            friend class D;
        }
   };
};
In this example, the first nonclass scope that encloses the friend declaration of class D is namespace A, so friend class D is in the scope of namespace A.

If the name of a friend class has been introduced before the friend declaration, the compiler searches for a class name that matches the name of the friend class beginning at the scope of the friend declaration. If the declaration of a nested class is followed by the declaration of a friend class with the same name, the nested class is a friend of the enclosing class.

If the friend function is a member of another class, you need to use the scope resolution operator (::). For example:
class A {
public:
  int f() { }
};

class B {
  friend int A::f();
};
Friends of a base class are not inherited by any classes derived from that base class. The following example demonstrates this:
class A {
  friend class B;
  int a;
};

class B { };

class C : public B {
  void f(A* p) {
    p->a = 2; // error
  }
};
The compiler does not support the statement p->a = 2 because class C is not a friend of class A, although C inherits from a friend of A.
Friendship is not transitive. The following example demonstrates this:
class A {
  friend class B;
  int a;
};

class B {
  friend class C;
};

class C {
  void f(A* p) {
    p->a = 2; // error
  }
};
The compiler does not accept the statement p->a = 2 because class C is not a friend of class A, although C is a friend of a friend of A.
If you declare a friend in a local class, and the friend name is unqualified, the compiler looks for the name only within the innermost enclosing nonclass scope. You must declare a function before declaring it as a friend of a local scope class. You do not have to do so with classes. The following example demonstrates this:
class X { };
void a();

void f() {
  class Y { };
  void b();
  class A {
    friend class X;
    friend class Y;
    friend class Z;
    friend void a(); // error
    friend void b();
    friend void c(); // error
  };
  ::X moocow;
    X moocow2; 
}
In the above example, the compiler accepts the following statements:
The compiler does not accept the following statements:
  • friend void a(): This statement does not consider function a() declared in namespace scope. Since function a() has not been declared in the scope of f(), the compiler does not accept this statement.
  • friend void c(): Since function c() has not been declared in the scope of f(), the compiler does not accept this statement.