The following example illustrates the differences between
members and friends:
class X {int a;
friendvoid friend_set(X*, int);
public:void member_set(int);
};
void friend_set(X* p, int i){ p->a = i; }void X::member_set(int i){ a = i; }void f(){
X obj;
friend_set(&obj,10);
obj.member_set(10);
}
Declaring a class to be a friend implies that private and
protected members of the class granting friendship can be named in the
base-specifiers and member declarations of the befriended
class.
[Example 2: class A {class B {};
friendclass X;
};
struct X : A::B {// OK, A::B accessible to friend
A::B mx; // OK, A::B accessible to member of friendclass Y {
A::B my; // OK, A::B accessible to nested member of friend};
};
— end example]
[Example 3: class X {enum{ a=100};
friendclass Y;
};
class Y {int v[X::a]; // OK, Y is a friend of X};
class Z {int v[X::a]; // error: X::a is private};
— end example]
If the
type specifier in a friend declaration designates a (possibly
cv-qualified) class type, that class is declared as a friend; otherwise, the
friend declaration is ignored.
[Example 4: class C;
typedef C Ct;
class X1 {friend C; // OK, class C is a friend};
class X2 {friend Ct; // OK, class C is a friendfriend D; // error: D not foundfriendclass D; // OK, elaborated-type-specifier declares new class};
template<typename T>class R {friend T;
};
R<C> rc; // class C is a friend of R<C>
R<int> Ri; // OK, "friend int;" is ignored — end example]
A friend declaration refers to an entity, not (all overloads of) a name.
A member function of a class
X
can be a friend of
a class
Y.
[Example 5: class Y {friendchar* X::foo(int);
friend X::X(char); // constructors can be friendsfriend X::~X(); // destructors can be friends};
— end example]
A function may be defined in a friend declaration of a class if and only if the
class is a non-local class ([class.local]) and the function name is unqualified.
[Example 6: class M {friendvoid f(){}// definition of global f, a friend of M,// not the definition of a member function};
— end example]
A member nominated by a friend declaration shall be accessible in the
class containing the friend declaration.
The meaning of the friend declaration is the same whether the friend declaration
appears in the private, protected, or public ([class.mem])
portion of the class
member-specification.
[Example 7: class A {friendclass B;
int a;
};
class B {friendclass C;
};
class C {void f(A* p){
p->a++; // error: C is not a friend of A despite being a friend of a friend}};
class D :public B {void f(A* p){
p->a++; // error: D is not a friend of A despite being derived from a friend}};
— end example]
[Example 8: // Assume f and g have not yet been declared.void h(int);
template<class T>void f2(T);
namespace A {class X {friendvoid f(X); // A::f(X) is a friendclass Y {friendvoid g(); // A::g is a friendfriendvoid h(int); // A::h is a friend// ::h not consideredfriendvoid f2<>(int); // ::f2<>(int) is a friend};
};
// A::f, A::g and A::h are not visible here
X x;
void g(){ f(x); }// definition of A::gvoid f(X){/* ... */}// definition of A::fvoid h(int){/* ... */}// definition of A::h// A::f, A::g and A::h are visible here and known to be friends}using A::x;
void h(){
A::f(x);
A::X::f(x); // error: f is not a member of A::X
A::X::Y::g(); // error: g is not a member of A::X::Y} — end example]
[Example 9: class X;
void a();
void f(){class Y;
externvoid b();
class A {friendclass X; // OK, but X is a local class, not ::Xfriendclass Y; // OKfriendclass Z; // OK, introduces local class Zfriendvoid a(); // error, ::a is not consideredfriendvoid b(); // OKfriendvoid c(); // error};
X* px; // OK, but ::X is found
Z* pz; // error: no Z is found} — end example]