This commit is contained in:
2025-10-25 03:02:53 +03:00
commit 043225d523
3416 changed files with 681196 additions and 0 deletions

673
cppdraft/class/access.md Normal file
View File

@@ -0,0 +1,673 @@
[class.access]
# 11 Classes [[class]](./#class)
## 11.8 Member access control [class.access]
### [11.8.1](#general) General [[class.access.general]](class.access.general)
[1](#general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4323)
A member of a class can be
- [(1.1)](#general-1.1)
private,
that is, it can be named only by members and friends
of the class in which it is declared;
- [(1.2)](#general-1.2)
protected,
that is, it can be named only by members and friends
of the class in which it is declared, by classes derived from that class, and by their
friends (see [[class.protected]](#class.protected "11.8.5Protected member access")); or
- [(1.3)](#general-1.3)
public,
that is, it can be named anywhere without access restriction[.](#general-1.sentence-1)
[*Note [1](#general-note-1)*:
A constructor or destructor can be named by an expression ([[basic.def.odr]](basic.def.odr "6.3One-definition rule"))
even though it has no name[.](#general-1.sentence-2)
— *end note*]
[2](#general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4347)
A member of a class can also access all the members to which the class has access[.](#general-2.sentence-1)
A local class of a member function may access
the same members that the member function itself may access[.](#general-2.sentence-2)[96](#footnote-96 "Access permissions are thus transitive and cumulative to nested and local classes.")
[3](#general-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4357)
Members of a class defined with the keywordclass are private by default[.](#general-3.sentence-1)
Members of a class defined with the keywordsstruct or union are public by default[.](#general-3.sentence-2)
[*Example [1](#general-example-1)*: class X {int a; // X::a is private by default};
struct S {int a; // S::a is public by default}; — *end example*]
[4](#general-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4379)
Access control is applied uniformly to declarations and expressions[.](#general-4.sentence-1)
[*Note [2](#general-note-2)*:
Access control applies to members nominated by
friend declarations ([[class.friend]](#class.friend "11.8.4Friends")) and[*using-declaration*](namespace.udecl#nt:using-declaration "9.10The using declaration[namespace.udecl]")*s* ([[namespace.udecl]](namespace.udecl "9.10The using declaration"))[.](#general-4.sentence-2)
— *end note*]
When a [*using-declarator*](namespace.udecl#nt:using-declarator "9.10The using declaration[namespace.udecl]") is named,
access control is applied to it, not to the declarations that replace it[.](#general-4.sentence-3)
For an overload set, access control is applied only to
the function selected by overload resolution[.](#general-4.sentence-4)
[*Example [2](#general-example-2)*: struct S {void f(int);private:void f(double);};
void g(S* sp) { sp->f(2); // OK, access control applied after overload resolution} — *end example*]
[*Note [3](#general-note-3)*:
Because access control applies to the declarations named,
if access control is applied to a type alias,
only the accessibility of the typedef or alias declaration itself is considered[.](#general-4.sentence-5)
The accessibility of the underlying entity is not considered[.](#general-4.sentence-6)
[*Example [3](#general-example-3)*: class A {class B { };public:typedef B BB;};
void f() { A::BB x; // OK, typedef A::BB is public A::B y; // access error, A::B is private} — *end example*]
— *end note*]
[5](#general-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4424)
[*Note [4](#general-note-4)*:
Access control does not prevent members from being found by name lookup or
implicit conversions to base classes from being considered[.](#general-5.sentence-1)
— *end note*]
The interpretation of a given construct is
established without regard to access control[.](#general-5.sentence-2)
If the interpretation
established makes use of inaccessible members or base classes,
the construct is ill-formed[.](#general-5.sentence-3)
[6](#general-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4435)
All access controls in [class.access] affect the ability to name a class member
from the declaration of a particular
entity, including parts of the declaration preceding the name of the entity
being declared and, if the entity is a class, the definitions of members of
the class appearing outside the class's [*member-specification*](class.mem.general#nt:member-specification "11.4.1General[class.mem.general]")[.](#general-6.sentence-1)
[*Note [5](#general-note-5)*:
This access also applies to implicit references to constructors,
conversion functions, and destructors[.](#general-6.sentence-2)
— *end note*]
[7](#general-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4446)
[*Example [4](#general-example-4)*: class A {typedef int I; // private member I f() pre(A::x > 0); friend I g(I) post(A::x <= 0); static I x; template<int> struct Q; template<int> friend struct R;protected:struct B { };};
A::I A::f() pre(A::x > 0) { return 0; } A::I g(A::I p = A::x) post(A::x <= 0);
A::I g(A::I p) { return 0; } A::I A::x = 0;template<A::I> struct A::Q { };template<A::I> struct R { };
struct D: A::B, A { };
Here, all the uses ofA::I are well-formed becauseA::f,A::x, and A::Q are members of classA andg and R are friends of classA[.](#general-7.sentence-1)
This implies, for example, that access checking on the first use ofA::I must be deferred until it is determined that this use ofA::I is as the return type of a member of classA[.](#general-7.sentence-2)
Similarly, the use of A::B as a[*base-specifier*](class.derived.general#nt:base-specifier "11.7.1General[class.derived.general]") is well-formed because D is derived from A, so checking of [*base-specifier*](class.derived.general#nt:base-specifier "11.7.1General[class.derived.general]")*s* must be deferred until the entire [*base-specifier-list*](class.derived.general#nt:base-specifier-list "11.7.1General[class.derived.general]") has been seen[.](#general-7.sentence-3)
— *end example*]
[8](#general-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4493)
Access is checked for a default argument ([[dcl.fct.default]](dcl.fct.default "9.3.4.7Default arguments"))
at the point of declaration,
rather than at any points of use of the default argument[.](#general-8.sentence-1)
Access checking for default arguments in function templates and in
member functions of class templates is performed as described in [[temp.inst]](temp.inst "13.9.2Implicit instantiation")[.](#general-8.sentence-2)
[9](#general-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4502)
Access for a default [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") ([[temp.param]](temp.param "13.2Template parameters"))
is checked in the context in which it appears rather than at any
points of use of it[.](#general-9.sentence-1)
[*Example [5](#general-example-5)*: class B { };template <class T> class C {protected:typedef T TT;};
template <class U, class V = typename U::TT>class D : public U { };
D <C<B> >* d; // access error, C::TT is protected — *end example*]
[96)](#footnote-96)[96)](#footnoteref-96)
Access
permissions are thus transitive and cumulative to nested
and local classes[.](#footnote-96.sentence-1)
### [11.8.2](#spec) Access specifiers [[class.access.spec]](class.access.spec)
[1](#spec-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4524)
Member declarations can be labeled by an[*access-specifier*](class.derived.general#nt:access-specifier "11.7.1General[class.derived.general]") ([[class.derived]](class.derived "11.7Derived classes")):
[*access-specifier*](class.derived.general#nt:access-specifier "11.7.1General[class.derived.general]") : [*member-specification*](class.mem.general#nt:member-specification "11.4.1General[class.mem.general]")opt
An[*access-specifier*](class.derived.general#nt:access-specifier "11.7.1General[class.derived.general]") specifies the access rules for members following it
until the end of the class or until another[*access-specifier*](class.derived.general#nt:access-specifier "11.7.1General[class.derived.general]") is encountered[.](#spec-1.sentence-2)
[*Example [1](#spec-example-1)*: class X {int a; // X::a is private by default: class usedpublic:int b; // X::b is publicint c; // X::c is public}; — *end example*]
[2](#spec-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4549)
Any number of access specifiers is allowed and no particular order is required[.](#spec-2.sentence-1)
[*Example [2](#spec-example-2)*: struct S {int a; // S::a is public by default: struct usedprotected:int b; // S::b is protectedprivate:int c; // S::c is privatepublic:int d; // S::d is public}; — *end example*]
[3](#spec-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4565)
When a member is redeclared within its class definition,
the access specified at its redeclaration shall
be the same as at its initial declaration[.](#spec-3.sentence-1)
[*Example [3](#spec-example-3)*: struct S {class A; enum E : int;private:class A { }; // error: cannot change accessenum E: int { e0 }; // error: cannot change access}; — *end example*]
[4](#spec-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4581)
[*Note [1](#spec-note-1)*:
In a derived class, the lookup of a base class name will find the
injected-class-name instead of the name of the base class in the scope
in which it was declared[.](#spec-4.sentence-1)
The injected-class-name might be less accessible
than the name of the base class in the scope in which it was declared[.](#spec-4.sentence-2)
— *end note*]
[*Example [4](#spec-example-4)*: class A { };class B : private A { };class C : public B { A* p; // error: injected-class-name A is inaccessible::A* q; // OK}; — *end example*]
### [11.8.3](#base) Accessibility of base classes and base class members [[class.access.base]](class.access.base)
[1](#base-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4607)
If a class is declared to be a base class ([[class.derived]](class.derived "11.7Derived classes")) for another class using thepublic access specifier, the
public members of the base class are accessible as
public members of the derived class and
protected members of the base class are accessible as
protected members of the derived class[.](#base-1.sentence-1)
If a class is declared to be a base class for another class using theprotected access specifier, the
public and protected members of the base class are accessible as
protected members of the derived class[.](#base-1.sentence-2)
If a class is declared to be a base class for another class using theprivate access specifier, the
public and protected
members of the base class are accessible as private
members of the derived class[.](#base-1.sentence-3)[97](#footnote-97 "As specified previously in [class.access], private members of a base class remain inaccessible even to derived classes unless friend declarations within the base class definition are used to grant access explicitly.")
[2](#base-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4633)
In the absence of an[*access-specifier*](class.derived.general#nt:access-specifier "11.7.1General[class.derived.general]") for a base class,public is assumed when the derived class is
defined with the [*class-key*](class.pre#nt:class-key "11.1Preamble[class.pre]")struct andprivate is assumed when the class is
defined with the [*class-key*](class.pre#nt:class-key "11.1Preamble[class.pre]")class[.](#base-2.sentence-1)
[*Example [1](#base-example-1)*: class B { /* ... */ };class D1 : private B { /* ... */ };class D2 : public B { /* ... */ };class D3 : B { /* ... */ }; // B private by defaultstruct D4 : public B { /* ... */ };struct D5 : private B { /* ... */ };struct D6 : B { /* ... */ }; // B public by defaultclass D7 : protected B { /* ... */ };struct D8 : protected B { /* ... */ };
HereB is a public base ofD2,D4,
andD6,
a private base ofD1,D3,
andD5,
and a protected base ofD7 andD8[.](#base-2.sentence-2)
— *end example*]
[3](#base-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4677)
[*Note [1](#base-note-1)*:
A member of a private base class can be inaccessible as inherited,
but accessible directly[.](#base-3.sentence-1)
Because of the rules on pointer conversions ([[conv.ptr]](conv.ptr "7.3.12Pointer conversions")) and
explicit casts ([[expr.type.conv]](expr.type.conv "7.6.1.4Explicit type conversion (functional notation)"), [[expr.static.cast]](expr.static.cast "7.6.1.9Static cast"), [[expr.cast]](expr.cast "7.6.3Explicit type conversion (cast notation)")),
a conversion from a pointer to a derived class to a pointer
to an inaccessible base class can be ill-formed if an implicit conversion
is used, but well-formed if an explicit cast is used[.](#base-3.sentence-2)
[*Example [2](#base-example-2)*: class B {public:int mi; // non-static memberstatic int si; // static member};class D : private B {};class DD : public D {void f();};
void DD::f() { mi = 3; // error: mi is private in D si = 3; // error: si is private in D::B b;
b.mi = 3; // OK (b.mi is different from this->mi) b.si = 3; // OK (b.si is different from this->si)::B::si = 3; // OK::B* bp1 = this; // error: B is a private base class::B* bp2 = (::B*)this; // OK with cast bp2->mi = 3; // OK, access through a pointer to B.} — *end example*]
— *end note*]
[4](#base-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4714)
A base classB ofN is[*accessible*](#def:accessible "11.8.3Accessibility of base classes and base class members[class.access.base]") at*R*,
if
- [(4.1)](#base-4.1)
an invented public member ofB would be a public member ofN, or
- [(4.2)](#base-4.2)
*R* occurs in a direct member or friend of classN,
and an invented public member ofB would be a private or protected member ofN, or
- [(4.3)](#base-4.3)
*R* occurs in a direct member or friend of a classP derived fromN,
and an invented public member ofB would be a private or protected member ofP, or
- [(4.4)](#base-4.4)
there exists a classS such thatB is a base class ofS accessible at*R* andS is a base class ofN accessible at*R*[.](#base-4.sentence-1)
[*Example [3](#base-example-3)*: class B {public:int m;};
class S: private B {friend class N;};
class N: private S {void f() { B* p = this; // OK because class S satisfies the fourth condition above: B is a base class of N// accessible in f() because B is an accessible base class of S and S is an accessible// base class of N.}}; — *end example*]
[5](#base-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4786)
If a base class is accessible, one can implicitly convert a pointer to
a derived class to a pointer to that base class ([[conv.ptr]](conv.ptr "7.3.12Pointer conversions"), [[conv.mem]](conv.mem "7.3.13Pointer-to-member conversions"))[.](#base-5.sentence-1)
[*Note [2](#base-note-2)*:
It follows that
members and friends of a classX can implicitly convert anX* to a pointer to a private or protected immediate base class ofX[.](#base-5.sentence-2)
— *end note*]
An expression E that designates a member m has a [*designating class*](#def:class,designating "11.8.3Accessibility of base classes and base class members[class.access.base]") that affects the access to m[.](#base-5.sentence-3)
This designating class is either
- [(5.1)](#base-5.1)
the innermost class of which m is directly a member
if E is a [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9Expression splicing[expr.prim.splice]") or
- [(5.2)](#base-5.2)
the class in whose scope name lookup performed a search
that found m otherwise[.](#base-5.sentence-4)
[*Note [3](#base-note-3)*:
This class can be explicit, e.g., when a[*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") is used, or implicit, e.g., when a class member access operator ([[expr.ref]](expr.ref "7.6.1.5Class member access")) is used (including cases where an implicit
“this->”
is
added)[.](#base-5.sentence-5)
If both a class member access operator and a[*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") are used to name the member (as inp->T::m),
the class designating the member is the class designated by the[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") of the[*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") (that is,T)[.](#base-5.sentence-6)
— *end note*]
A memberm is accessible at the point*R* when designated in classN if
- [(5.3)](#base-5.3)
m is designated by a [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9Expression splicing[expr.prim.splice]"), or
- [(5.4)](#base-5.4)
m as a member ofN is public, or
- [(5.5)](#base-5.5)
m as a member ofN is private, and*R* occurs in a direct member or friend of classN,
or
- [(5.6)](#base-5.6)
m as a member ofN is protected, and*R* occurs in a direct member or friend of classN,
or in a member of a classP derived fromN,
wherem as a member ofP is public, private, or protected, or
- [(5.7)](#base-5.7)
there exists a base classB ofN that is accessible at*R*,
andm is accessible at*R* when designated in classB[.](#base-5.sentence-7)
[*Example [4](#base-example-4)*: class B;class A {private:int i; friend void f(B*);};class B : public A { };void f(B* p) { p->i = 1; // OK, B* can be implicitly converted to A*, and f has access to i in A} — *end example*]
[6](#base-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4898)
If a class member access operator, including an implicit
“this->”,
is used to access a non-static data member or non-static
member function, the reference is ill-formed if the
left operand (considered as a pointer in the
“.”
operator case) cannot be implicitly converted to a
pointer to the designating class of the right operand[.](#base-6.sentence-1)
[*Note [4](#base-note-4)*:
This requirement is in addition to the requirement that
the member be accessible as designated[.](#base-6.sentence-2)
— *end note*]
[97)](#footnote-97)[97)](#footnoteref-97)
As specified previously in [class.access],
private members of a base class remain inaccessible even to derived classes
unless friend
declarations within the base class definition are used to grant access explicitly[.](#footnote-97.sentence-1)
### [11.8.4](#class.friend) Friends [[class.friend]](class.friend)
[1](#class.friend-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[.](#class.friend-1.sentence-1)
A class specifies its friends, if any, by way of friend declarations[.](#class.friend-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[.](#class.friend-1.sentence-3)
[*Example [1](#class.friend-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](#class.friend-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.1General[class.derived.general]")*s* and member declarations of the befriended
class[.](#class.friend-2.sentence-1)
[*Example [2](#class.friend-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](#class.friend-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](#class.friend-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.1General[class.mem.general]")[.](#class.friend-3.sentence-1)
[*Note [1](#class.friend-note-1)*:
A friend declaration can be the[*declaration*](dcl.pre#nt:declaration "9.1Preamble[dcl.pre]") in
a [*template-declaration*](temp.pre#nt:template-declaration "13.1Preamble[temp.pre]") ([[temp.pre]](temp.pre "13.1Preamble"), [[temp.friend]](temp.friend "13.7.5Friends"))[.](#class.friend-3.sentence-2)
— *end note*]
If a [*friend-type-specifier*](class.mem.general#nt:friend-type-specifier "11.4.1General[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.1General[class.mem.general]") is ignored[.](#class.friend-3.sentence-3)
[*Example [4](#class.friend-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](#class.friend-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5032)
[*Note [2](#class.friend-note-2)*:
A friend declaration refers to an entity, not (all overloads of) a name[.](#class.friend-4.sentence-1)
A member function of a classX can be a friend of
a classY[.](#class.friend-4.sentence-2)
[*Example [5](#class.friend-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](#class.friend-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.6Local class declarations")) and the function name is unqualified[.](#class.friend-5.sentence-1)
[*Example [6](#class.friend-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](#class.friend-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.8The inline specifier")) function
if it is attached to the global module[.](#class.friend-6.sentence-1)
[*Note [3](#class.friend-note-3)*:
If a friend function is defined outside a class,
it is not in the scope of the class[.](#class.friend-6.sentence-2)
— *end note*]
[7](#class.friend-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5074)
No[*storage-class-specifier*](dcl.stc#nt:storage-class-specifier "9.2.2Storage class specifiers[dcl.stc]") shall appear in the[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") of a friend declaration[.](#class.friend-7.sentence-1)
[8](#class.friend-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[.](#class.friend-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.4Class members"))
portion of the class[*member-specification*](class.mem.general#nt:member-specification "11.4.1General[class.mem.general]")[.](#class.friend-8.sentence-2)
[9](#class.friend-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5090)
Friendship is neither inherited nor transitive[.](#class.friend-9.sentence-1)
[*Example [7](#class.friend-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](#class.friend-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5118)
[*Note [4](#class.friend-note-4)*:
A friend declaration never binds any names ([[dcl.meaning]](dcl.meaning "9.3.4Meaning of declarators"), [[dcl.type.elab]](dcl.type.elab "9.2.9.5Elaborated type specifiers"))[.](#class.friend-10.sentence-1)
— *end note*]
[*Example [8](#class.friend-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](#class.friend-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*]
### [11.8.5](#class.protected) Protected member access [[class.protected]](class.protected)
[1](#class.protected-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5181)
An additional access check beyond those described earlier in [class.access]
is applied when a non-static data member or non-static member function is a
protected member of its naming class ([[class.access.base]](#base "11.8.3Accessibility of base classes and base class members"))[.](#class.protected-1.sentence-1)[98](#footnote-98 "This additional check does not apply to other members, e.g., static data members or enumerator member constants.")
As described earlier, access to a protected member is granted because the
reference occurs in a friend or direct member of some class C[.](#class.protected-1.sentence-2)
If the access is
to form a pointer to member ([[expr.unary.op]](expr.unary.op "7.6.2.2Unary operators")), the[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") shall denote C or a class derived fromC[.](#class.protected-1.sentence-3)
All other accesses involve a (possibly implicit) object
expression ([[expr.ref]](expr.ref "7.6.1.5Class member access"))[.](#class.protected-1.sentence-4)
In this case, the class of the object expression shall beC or a class derived from C[.](#class.protected-1.sentence-5)
[*Example [1](#class.protected-example-1)*: class B {protected:int i; static int j;};
class D1 : public B {};
class D2 : public B {friend void fr(B*,D1*,D2*); void mem(B*,D1*);};
void fr(B* pb, D1* p1, D2* p2) { pb->i = 1; // error p1->i = 2; // error p2->i = 3; // OK (access through a D2) p2->B::i = 4; // OK (access through a D2, even though naming class is B)int B::* pmi_B = &B::i; // errorint B::* pmi_B2 = &D2::i; // OK (type of &D2::i is int B::*) B::j = 5; // error: not a friend of naming class B D2::j = 6; // OK (because refers to static member)}void D2::mem(B* pb, D1* p1) { pb->i = 1; // error p1->i = 2; // error i = 3; // OK (access through this) B::i = 4; // OK (access through this, qualification ignored)int B::* pmi_B = &B::i; // errorint B::* pmi_B2 = &D2::i; // OK j = 5; // OK (because j refers to static member) B::j = 6; // OK (because B::j refers to static member)}void g(B* pb, D1* p1, D2* p2) { pb->i = 1; // error p1->i = 2; // error p2->i = 3; // error} — *end example*]
[98)](#footnote-98)[98)](#footnoteref-98)
This
additional check does not apply to other members,
e.g., static data members or enumerator member constants[.](#footnote-98.sentence-1)
### [11.8.6](#virt) Access to virtual functions [[class.access.virt]](class.access.virt)
[1](#virt-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5246)
The access rules ([class.access]) for a virtual function are determined by its declaration
and are not affected by the rules for a function that later overrides it[.](#virt-1.sentence-1)
[*Example [1](#virt-example-1)*: class B {public:virtual int f();};
class D : public B {private:int f();};
void f() { D d;
B* pb = &d;
D* pd = &d;
pb->f(); // OK, B::f() is public, D::f() is invoked pd->f(); // error: D::f() is private} — *end example*]
[2](#virt-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5272)
Access is checked at the call point using the type of the expression used
to denote the object for which the member function is called
(B* in the example above)[.](#virt-2.sentence-1)
The access of the member function in the class in which it was defined
(D in the example above) is in general not known[.](#virt-2.sentence-2)
### [11.8.7](#class.paths) Multiple access [[class.paths]](class.paths)
[1](#class.paths-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5284)
If a declaration can be reached by several paths through a multiple inheritance
graph, the access is that of the path that gives most access[.](#class.paths-1.sentence-1)
[*Example [1](#class.paths-example-1)*: class W { public: void f(); };class A : private virtual W { };class B : public virtual W { };class C : public A, public B {void f() { W::f(); } // OK};
SinceW::f() is available toC::f() along the public path throughB,
access is allowed[.](#class.paths-1.sentence-2)
— *end example*]
### [11.8.8](#nest) Nested classes [[class.access.nest]](class.access.nest)
[1](#nest-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5310)
A nested class is a member and as such has the same access rights as any other member[.](#nest-1.sentence-1)
The members of an enclosing class have no special access to members of a nested
class; the usual access rules ([class.access]) shall be obeyed[.](#nest-1.sentence-2)
[*Example [1](#nest-example-1)*: class E {int x; class B { }; class I { B b; // OK, E::I can access E::Bint y; void f(E* p, int i) { p->x = i; // OK, E::I can access E::x}}; int g(I* p) {return p->y; // error: I::y is private}}; — *end example*]