8.7 KiB
[class.access.base]
11 Classes [class]
11.8 Member access control [class.access]
11.8.3 Accessibility of base classes and base class members [class.access.base]
If a class is declared to be a base class ([class.derived]) 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.
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.
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.97
In the absence of anaccess-specifier for a base class,public is assumed when the derived class is defined with the class-keystruct andprivate is assumed when the class is defined with the class-keyclass.
[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.
â end example]
[Note 1:
A member of a private base class can be inaccessible as inherited, but accessible directly.
Because of the rules on pointer conversions ([conv.ptr]) and explicit casts ([expr.type.conv], [expr.static.cast], [expr.cast]), 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.
[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]
A base classB ofN isaccessible atR, if
an invented public member ofB would be a public member ofN, or
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
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
there exists a classS such thatB is a base class ofS accessible atR andS is a base class ofN accessible atR.
[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]
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 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.
â end note]
An expression E that designates a member m has a designating class that affects the access to m.
This designating class is either
the innermost class of which m is directly a member if E is a splice-expression or
the class in whose scope name lookup performed a search that found m otherwise.
[Note 3:
This class can be explicit, e.g., when aqualified-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 aqualified-id are used to name the member (as inp->T::m), the class designating the member is the class designated by thenested-name-specifier of thequalified-id (that is,T).
â end note]
A memberm is accessible at the pointR when designated in classN if
m is designated by a splice-expression, or
m as a member ofN is public, or
m as a member ofN is private, andR occurs in a direct member or friend of classN, or
m as a member ofN is protected, andR 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
there exists a base classB ofN that is accessible atR, andm is accessible atR when designated in classB. [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]
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.
[Note 4:
This requirement is in addition to the requirement that the member be accessible as designated.
â end note]
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.