[class.friend] # 11 Classes [[class]](./#class) ## 11.8 Member access control [[class.access]](class.access#class.friend) ### 11.8.4 Friends [class.friend] [1](#1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4916) A friend of a class is a function or class that is given permission to name the private and protected members of the class[.](#1.sentence-1) A class specifies its friends, if any, by way of friend declarations[.](#1.sentence-2) Such declarations give special access rights to the friends, but they do not make the nominated friends members of the befriending class[.](#1.sentence-3) [*Example [1](#example-1)*: The following example illustrates the differences between members and friends:class X {int a; friend void 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);} — *end example*] [2](#2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4946) Declaring a class to be a friend implies that private and protected members of the class granting friendship can be named in the[*base-specifier*](class.derived.general#nt:base-specifier "11.7.1 General [class.derived.general]")*s* and member declarations of the befriended class[.](#2.sentence-1) [*Example [2](#example-2)*: class A {class B { }; friend class 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](#example-3)*: class X {enum { a=100 }; friend class 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*] [3](#3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4984) A friend declaration that does not declare a function shall be a [*friend-type-declaration*](class.mem.general#nt:friend-type-declaration "11.4.1 General [class.mem.general]")[.](#3.sentence-1) [*Note [1](#note-1)*: A friend declaration can be the[*declaration*](dcl.pre#nt:declaration "9.1 Preamble [dcl.pre]") in a [*template-declaration*](temp.pre#nt:template-declaration "13.1 Preamble [temp.pre]") ([[temp.pre]](temp.pre "13.1 Preamble"), [[temp.friend]](temp.friend "13.7.5 Friends"))[.](#3.sentence-2) — *end note*] If a [*friend-type-specifier*](class.mem.general#nt:friend-type-specifier "11.4.1 General [class.mem.general]") in a friend declaration designates a (possibly cv-qualified) class type, that class is declared as a friend; otherwise, the[*friend-type-specifier*](class.mem.general#nt:friend-type-specifier "11.4.1 General [class.mem.general]") is ignored[.](#3.sentence-3) [*Example [4](#example-4)*: class C;typedef C Ct;class E; class X1 {friend C; // OK, class C is a friend}; class X2 {friend Ct; // OK, class C is a friendfriend D; // error: D not foundfriend class D; // OK, elaborated-type-specifier declares new class}; template class R {friend Ts...;}; template class R, R> {friend Ts::Nested..., Us...;}; R rc; // class C is a friend of R R rce; // classes C and E are friends of R R Ri; // OK, “friend int;'' is ignoredstruct E { struct Nested; }; R, R> rr; // E​::​Nested and C are friends of R, R> — *end example*] [4](#4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5032) [*Note [2](#note-2)*: A friend declaration refers to an entity, not (all overloads of) a name[.](#4.sentence-1) A member function of a classX can be a friend of a classY[.](#4.sentence-2) [*Example [5](#example-5)*: class Y {friend char* X::foo(int); friend X::X(char); // constructors can be friendsfriend X::~X(); // destructors can be friends}; — *end example*] — *end note*] [5](#5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5053) 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]](class.local "11.6 Local class declarations")) and the function name is unqualified[.](#5.sentence-1) [*Example [6](#example-6)*: class M {friend void f() { } // definition of global f, a friend of M,// not the definition of a member function}; — *end example*] [6](#6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5066) Such a function is implicitly an inline ([[dcl.inline]](dcl.inline "9.2.8 The inline specifier")) function if it is attached to the global module[.](#6.sentence-1) [*Note [3](#note-3)*: If a friend function is defined outside a class, it is not in the scope of the class[.](#6.sentence-2) — *end note*] [7](#7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5074) No[*storage-class-specifier*](dcl.stc#nt:storage-class-specifier "9.2.2 Storage class specifiers [dcl.stc]") shall appear in the[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") of a friend declaration[.](#7.sentence-1) [8](#8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5081) A member nominated by a friend declaration shall be accessible in the class containing the friend declaration[.](#8.sentence-1) The meaning of the friend declaration is the same whether the friend declaration appears in the private, protected, or public ([[class.mem]](class.mem "11.4 Class members")) portion of the class[*member-specification*](class.mem.general#nt:member-specification "11.4.1 General [class.mem.general]")[.](#8.sentence-2) [9](#9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5090) Friendship is neither inherited nor transitive[.](#9.sentence-1) [*Example [7](#example-7)*: class A {friend class B; int a;}; class B {friend class 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*] [10](#10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5118) [*Note [4](#note-4)*: A friend declaration never binds any names ([[dcl.meaning]](dcl.meaning "9.3.4 Meaning of declarators"), [[dcl.type.elab]](dcl.type.elab "9.2.9.5 Elaborated type specifiers"))[.](#10.sentence-1) — *end note*] [*Example [8](#example-8)*: // Assume f and g have not yet been declared.void h(int);template void f2(T);namespace A {class X {friend void f(X); // A​::​f(X) is a friendclass Y {friend void g(); // A​::​g is a friendfriend void h(int); // A​::​h is a friend// ​::​h not consideredfriend void 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](#example-9)*: class X;void a();void f() {class Y; extern void b(); class A {friend class X; // OK, but X is a local class, not ​::​Xfriend class Y; // OKfriend class Z; // OK, introduces local class Zfriend void a(); // error, ​::​a is not consideredfriend void b(); // OKfriend void c(); // error}; X* px; // OK, but ​::​X is found Z* pz; // error: no Z is found} — *end example*]