______________________________________________________________________
11 Member access control [class.access]
______________________________________________________________________
1 A member of a class can be
--private; that is, its name can be used only by member functions,
static data members, and friends of the class in which it is
declared.
--protected; that is, its name can be used only by member functions,
static data members, and friends of the class in which it is
declared and by member functions, static data members, and friends
of classes derived from this class (see _class.protected_).
--public; that is, its name can be used anywhere without access
restriction.
2 Members of a class defined with the keyword class are private by
default. Members of a class defined with the keywords struct or union
are public by default. [Example:
class X {
int a; // X::a is private by default
};
struct S {
int a; // S::a is public by default
};
--end example]
3 Access control is applied uniformly to all names, whether the names
are referred to from declarations or expressions. [Note: access con-
trol applies to names nominated by friend declarations
(_class.friend_) and using-declarations (_namespace.udecl_). ] In the
case of overloaded function names, access control is applied to the
function selected by overload resolution. [Note: because access con-
trol applies to names, if access control is applied to a typedef name,
only the accessibility of the typedef name itself is considered. The
accessibility of the entity referred to by the typedef is not consid-
ered. For example,
class A
{
class B { };
public:
typedef B BB;
};
void f()
{
A::BB x; // ok, typedef name A::BB is public
A::B y; // access error, A::B is private
}
--end note]
4 It should be noted that it is access to members and base classes that
is controlled, not their visibility. Names of members are still visi-
ble, and implicit conversions to base classes are still considered,
when those members and base classes are inaccessible. The interpreta-
tion of a given construct is established without regard to access con-
trol. If the interpretation established makes use of inaccessible
member names or base classes, the construct is ill-formed.
5 All access controls in this clause affect the ability to access a
class member name from a particular scope. In particular, access con-
trols apply as usual to member names accessed as part of a function
return type, even though it is not possible to determine the access
privileges of that use without first parsing the rest of the function.
[Example:
class A {
typedef int I; // private member
I f();
friend I g(I);
static I x;
};
A::I A::f() { return 0; }
A::I g(A::I p = A::x);
A::I g(A::I p) { return 0; }
A::I A::x = 0;
Here, all the uses of A::I are well-formed because A::f and A::x are
members of class A and g is a friend of class A. This implies, for
example, that access checking on the first use of A::I must be
deferred until it is determined that this use of A::I is as the return
type of a member of class A. ]
6 In the definition of a member of a nested class that appears outside
of its class definition, the name of the member may be qualified by
the names of enclosing classes of the member's class even if these
names are private members of their enclosing classes. [Example:
class D {
class E {
static int m;
};
};
int D::E::m = 1; // Okay, no access error on private `E'
--end example]
7 The names in a default argument expression (_dcl.fct.default_) are
bound at the point of declaration, and access is checked at that point
rather than at any points of use of the default argument expression.
11.1 Access specifiers [class.access.spec]
1 Member declarations can be labeled by an access-specifier
(_class.derived_):
access-specifier : member-specificationopt
An access-specifier specifies the access rules for members following
it until the end of the class or until another access-specifier is
encountered. [Example:
class X {
int a; // X::a is private by default: `class' used
public:
int b; // X::b is public
int c; // X::c is public
};
--end example] Any number of access specifiers is allowed and no par-
ticular order is required. [Example:
struct S {
int a; // S::a is public by default: `struct' used
protected:
int b; // S::b is protected
private:
int c; // S::c is private
public:
int d; // S::d is public
};
--end example]
2 The order of allocation of data members with separate access-specifier
labels is unspecified (_class.mem_).
3 When a member is redeclared within its class definition, the access
specified at its redeclaration shall be the same as at its initial
declaration. [Example:
struct S {
class A;
private:
class A { }; // error: cannot change access
};
--end example]
11.2 Accessibility of base classes and base [class.access.base]
class members
1 If a class is declared to be a base class (_class.derived_) for
another class using the public 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. If a class is declared to be a base
class for another class using the protected access specifier, the pub-
lic and protected members of the base class are accessible as pro-
tected members of the derived class. If a class is declared to be a
base class for another class using the private access specifier, the
public and protected members of the base class are accessible as pri-
vate members of the derived class1).
_________________________
1) As specified previously in _class.access_, private members of a
2 In the absence of an access-specifier for a base class, public is
assumed when the derived class is declared struct and private is
assumed when the class is declared class. [Example:
class B { /* ... */ };
class D1 : private B { /* ... */ };
class D2 : public B { /* ... */ };
class D3 : B { /* ... */ }; // `B' private by default
struct D4 : public B { /* ... */ };
struct D5 : private B { /* ... */ };
struct D6 : B { /* ... */ }; // `B' public by default
class D7 : protected B { /* ... */ };
struct D8 : protected B { /* ... */ };
Here B is a public base of D2, D4, and D6, a private base of D1, D3,
and D5, and a protected base of D7 and D8. --end example]
3 [Note: A member of a private base class might be inaccessible as an
inherited member name, but accessible directly. Because of the rules
on pointer conversions (_conv.ptr_) and explicit casts (_expr.cast_),
a conversion from a pointer to a derived class to a pointer to an
inaccessible base class might be ill-formed if an implicit conversion
is used, but well-formed if an explicit cast is used. For example,
class B {
public:
int mi; // nonstatic member
static 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; // okay (b.mi is different from this->mi)
b.si = 3; // okay (b.si is different from this->si)
B::si = 3; // okay
B* bp1 = this; // error: B is a private base class
B* bp2 = (B*)this; // okay with cast
bp2->mi = 3; // okay: access through a pointer to B.
}
--end note]
4 A base class is said to be accessible if an invented public member of
the base class is accessible. 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.mem_). [Note: it follows that members
and friends of a class X can implicitly convert an X* to a pointer to
_________________________
base class remain inaccessible even to derived classes unless friend
declarations within the base class declaration are used to grant ac-
cess explicitly.
a private or protected immediate base class of X. ] The access to a
member is affected by the class in which the member is named. This
naming class is the class in which the member name was looked up and
found. [Note: this class can be explicit, e.g., when a qualified-id
is used, or implicit, e.g., when a class member access operator
(_expr.ref_) is used (including cases where an implicit this->" is
added. If both a class member access operator and a qualified-id are
used to name the member (as in p->T::m), the class naming the member
is the class named by the nested-name-specifier of the qualified-id
(that is, T). ] A member m is accessible when named in class N if
--m as a member of N is public, or
--m as a member of N is private or protected, and the reference occurs
in a member or friend of class N, or
--there exists a base class B of N that is accessible at the point of
reference, and m is accessible when named in class B. [Example:
class B;
class A {
private:
int i;
friend void f(B*);
};
class B : public A { };
void f(B* p) {
p->i = 1; // Okay: B* can be implicitly cast to A*,
// and f has access to i in A
}
--end example]
11.3 Access declarations [class.access.dcl]
1 The access of a member of a base class can be changed in the derived
class by mentioning its qualified-id in the derived class declaration.
Such mention is called an access declaration. The effect of an access
declaration qualified-id ; is defined to be equivalent to the declara-
tion using qualified-id ;.2)
2 [Example:
class A {
public:
int z;
int z1;
};
_________________________
2) Access declarations are deprecated; member using-declarations
(_namespace.udecl_) provide a better means of doing the same things.
In earlier versions of the C++ language, access declarations were more
limited; they were generalized and made equivalent to using-declara-
tions in the interest of simplicity. Programmers are encouraged to
use using-declarations, rather than the new capabilities of access
declarations, in new code.
class B : public A {
int a;
public:
int b, c;
int bf();
protected:
int x;
int y;
};
class D : private B {
int d;
public:
B::c; // adjust access to `B::c'
B::z; // adjust access to `A::z'
A::z1; // adjust access to `A::z1'
int e;
int df();
protected:
B::x; // adjust access to `B::x'
int g;
};
class X : public D {
int xf();
};
int ef(D&);
int ff(X&);
The external function ef can use only the names c, z, z1, e, and df.
Being a member of D, the function df can use the names b, c, z, z1,
bf, x, y, d, e, df, and g, but not a. Being a member of B, the func-
tion bf can use the members a, b, c, z, z1, bf, x, and y. The func-
tion xf can use the public and protected names from D, that is, c, z,
z1, e, and df (public), and x, and g (protected). Thus the external
function ff has access only to c, z, z1, e, and df. If D were a pro-
tected or private base class of X, xf would have the same privileges
as before, but ff would have no access at all. ]
11.4 Friends [class.friend]
1 A friend of a class is a function or class that is not a member of the
class but is permitted to use the private and protected member names
from the class. The name of a friend is not in the scope of the
class, and the friend is not called with the member access operators
(_expr.ref_) unless it is a member of another class. [Example: 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 Declaring a class to be a friend implies that the names of private and
protected members from the class granting friendship can be accessed
in declarations of members of the befriended class. [Note: this means
that access to private and protected names is also granted to member
functions of the friend class (as if the functions were each friends)
and to the static data member definitions of the friend class. This
also means that private and protected type names from the class grant-
ing friendship can be used in the base-clause of a nested class of the
friend class. However, the declarations of members of classes nested
within the friend class cannot access the names of private and pro-
tected members from the class granting friendship. Also, because the
base-clause of the friend class is not part of its member declara-
tions, the base-clause of the friend class cannot access the names of
the private and protected members from the class granting friendship.
For example,
class A {
class B { };
friend class X;
};
class X : A::B { // ill-formed: A::B cannot be accessed
// in the base-clause for X
A::B mx; // ok: A::B used to declare member of X
class Y : A::B { // ok: A::B used to declare member of X
A::B my; // ill-formed: A::B cannot be accessed
// to declare members of nested class of X
};
};
] An elaborated-type-specifier shall be used in a friend declaration
for a class.3) A class shall not be defined in a friend declaration.
[Example:
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) The class-key of the elaborated-type-specifier is required.
3 A function first declared in a friend declaration has external linkage
(_basic.link_). Otherwise, the function retains its previous linkage
(_dcl.stc_).
4 When a friend declaration refers to an overloaded name or operator,
only the function specified by the parameter types becomes a friend.
A member function of a class X can be a friend of a class Y. [Exam-
ple:
class Y {
friend char* X::foo(int);
// ...
};
--end example]
5 A function can be defined in a friend declaration of a class if and
only if the class is a non-local class (_class.local_), the function
name is unqualified, and the function has namespace scope. [Example:
class M {
friend void f() { } // definition of global f, a friend of M,
// not the definition of a member function
};
--end example] Such a function is implicitly inline. A friend func-
tion defined in a class is in the (lexical) scope of the class in
which it is defined. A friend function defined outside the class is
not (_basic.lookup.unqual_).
6 No storage-class-specifier shall appear in the decl-specifier-seq of a
friend declaration.
7 A name nominated by a friend declaration shall be accessible in the
scope of 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.
8 Friendship is neither inherited nor transitive. [Example:
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]
9 If a friend declaration appears in a local class (_class.local_) and
the name specified is an unqualified name, a prior declaration is
looked up without considering scopes that are outside the innermost
enclosing non-class scope. For a friend function declaration, if
there is no prior declaration, the program is ill-formed. For a
friend class declaration, if there is no prior declaration, the class
that is specified belongs to the innermost enclosing non-class scope,
but if it is subsequently referenced, its name is not found by name
lookup until a matching declaration is provided in the innermost
enclosing nonclass scope. [Example:
class X;
void a();
void f() {
class Y;
extern void b();
class A {
friend class X; // okay, but X is a local class, not ::X
friend class Y; // okay
friend class Z; // okay, introduces local class Z
friend void a(); // error, ::a is not considered
friend void b(); // okay
friend void c(); // error
};
X *px; // okay, but ::X is found
Z *pz; // error, no Z is found
}
--end example]
11.5 Protected member access [class.protected]
1 When a friend or a member function of a derived class references a
protected nonstatic member of a base class, an access check applies in
addition to those described earlier in this clause.4) Except when
forming a pointer to member (_expr.unary.op_), the access must be
through a pointer to, reference to, or object of the derived class
itself (or any class derived from that class) (_expr.ref_). If the
access is to form a pointer to member, the nested-name-specifier shall
name the derived class (or any class derived from that class). [Exam-
ple:
_________________________
4) This additional check does not apply to other members, e.g. static
data members or enumerator member constants.
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; // ill-formed
p1->i = 2; // ill-formed
p2->i = 3; // ok (access through a D2)
p2->B::i = 4; // ok (access through a D2, qualification ignored)
int B::* pmi_B = &B::i; // ill-formed
int B::* pmi_B2 = &D2::i; // ok (type of &D2::i is "int B::*")
B::j = 5; // ok (because refers to static member)
D2::j =6; // ok (because refers to static member)
}
void D2::mem(B* pb, D1* p1)
{
pb->i = 1; // ill-formed
p1->i = 2; // ill-formed
i = 3; // ok (access through `this')
B::i = 4; // ok (access through `this', qualification ignored)
j = 5; // ok (because refers to static member)
B::j = 6; // ok (because refers to static member)
}
void g(B* pb, D1* p1, D2* p2)
{
pb->i = 1; // ill-formed
p1->i = 2; // ill-formed
p2->i = 3; // ill-formed
}
--end example]
11.6 Access to virtual functions [class.access.virt]
1 The access rules (_class.access_) for a virtual function are deter-
mined by its declaration and are not affected by the rules for a func-
tion that later overrides it. [Example:
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] 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). The access of the member func-
tion in the class in which it was defined (D in the example above) is
in general not known.
11.7 Multiple access [class.paths]
1 If a name can be reached by several paths through a multiple inheri-
tance graph, the access is that of the path that gives most access.
[Example:
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
};
Since W::f() is available to C::f() along the public path through B,
access is allowed. ]
11.8 Nested classes [class.access.nest]
1 The members of a nested class have no special access to members of an
enclosing class, nor to classes or functions that have granted friend-
ship to an enclosing class; the usual access rules (_class.access_)
shall be obeyed. 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. [Example:
class E {
int x;
class B { };
class I {
B b; // error: E::B is private
int y;
void f(E* p, int i)
{
p->x = i; // error: E::x is private
}
};
int g(I* p)
{
return p->y; // error: I::y is private
}
};
--end example]
2 [Note: because a base-clause for a nested class is part of the decla-
ration of the nested class itself (and not part of the declarations of
the members of the nested class), the base-clause may refer to the
private members of the enclosing class. For example,
class C {
class A { };
A *p; // ok
class B : A // ok
{
A *q; // okay because of injection of name A in A
C::A *r; // error, C::A is inaccessible
B *s; // okay because of injection of name B in B
C::B *t; // error, C::B is inaccessible
};
};
--end note]