[class.access.base] (original) (raw)
11 Classes [class]
11.9 Member access control [class.access]
11.9.2 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 thepublicaccess 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 theprotectedaccess 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 theprivateaccess specifier, the public and protected members of the base class are accessible as private members of the derived class.112
In the absence of anaccess-specifierfor a base class,publicis assumed when the derived class is defined with the class-key structandprivateis assumed when the class is defined with the class-key class.
[ Example
:
class B { };
class D1 : private B { };
class D2 : public B { };
class D3 : B { };
struct D4 : public B { };
struct D5 : private B { };
struct D6 : B { };
class D7 : protected B { };
struct D8 : protected B { };
HereBis a public base ofD2,D4, andD6, a private base ofD1,D3, andD5, and a protected base ofD7andD8.
— end example
]
[ 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.type.conv], [expr.static.cast], [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;
static int si;
};
class D : private B {
};
class DD : public D {
void f();
};
void DD::f() {
mi = 3;
si = 3;
::B b;
b.mi = 3;
b.si = 3;
::B::si = 3;
::B* bp1 = this;
::B* bp2 = (::B*)this;
bp2->mi = 3;
}
— end note
]
A base classBofNisaccessibleatR, if
- an invented public member ofBwould be a public member ofN, or
- Roccurs in a member or friend of classN, and an invented public member ofBwould be a private or protected member ofN, or
- Roccurs in a member or friend of a classPderived fromN, and an invented public member ofBwould be a private or protected member ofP, or
- there exists a classSsuch thatBis a base class ofSaccessible atRandSis a base class ofNaccessible atR.
[ Example
:
class B { public: int m; };
class S: private B { friend class N; };
class N: private S { void f() { B* p = this;
} };
— 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
:
It follows that members and friends of a classXcan implicitly convert anX*to a pointer to a private or protected immediate base class ofX.
— end note
]
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 aqualified-idis 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-idare used to name the member (as inp->T::m), the class naming the member is the class denoted by thenested-name-specifierof thequalified-id(that is,T).
— end note
]
A membermis accessible at the pointRwhen named in classNif
- mas a member ofNis public, or
- mas a member ofNis private, andRoccurs in a member or friend of classN, or
- mas a member ofNis protected, andRoccurs in a member or friend of classN, or in a member of a classPderived fromN, wheremas a member ofPis public, private, or protected, or
- there exists a base classBofNthat is accessible atR, andmis accessible atRwhen named in classB.
[ Example
:
class B;
class A {
private:
int i;
friend void f(B*);
};
class B : public A { };
void f(B* p) {
p->i = 1;
}
— 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 naming class of the right operand.
[ Note
:
This requirement is in addition to the requirement that the member be accessible as named.
— end note
]