Init
This commit is contained in:
167
cppdraft/class/friend.md
Normal file
167
cppdraft/class/friend.md
Normal file
@@ -0,0 +1,167 @@
|
||||
[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 <typename ... Ts> class R {friend Ts...;};
|
||||
|
||||
template <class... Ts, class... Us>class R<R<Ts...>, R<Us...>> {friend Ts::Nested..., Us...;};
|
||||
|
||||
R<C> rc; // class C is a friend of R<C> R<C, E> rce; // classes C and E are friends of R<C, E> R<int> Ri; // OK, âfriend int;'' is ignoredstruct E { struct Nested; };
|
||||
|
||||
R<R<E>, R<C, int>> rr; // E::Nested and C are friends of R<R<E>, R<C, int>> â *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 <class T> 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*]
|
||||
Reference in New Issue
Block a user