Below is a subtle example of accessing an instance's protected field x. B is a subclass of A so any variable of type B is also of type A. Why can B::foo() access b's x field, but not a's x field?
class A { protected: int x; }; class B : public A { protected: A *a; B *b; public: void foo() { int u = x; // OK : accessing inherited protected field x int v = b->x; // OK : accessing b's protected field x int w = a->x; // ERROR : accessing a's protected field x } };
Here is the error I get with g++
$ g++ -c A.cpp A.cpp: In member function ‘void B::foo()’: A.cpp:3: error: ‘int A::x’ is protected A.cpp:14: error: within this context
Since B
is publicly inherited from A
, A's protected member(s) become B's protected member(s), so B can access its protected members as usual from its member function(s). That is, the objects of B
can access the protected members of B
from its member functions.
But A's protected members cannot be accessed outside the class, using object of type A
.
Here is the relevant text from the Standard (2003)
11.5 Protected member access [class.protected]
When a friend or a member function of a derived class references a protected nonstatic member function or protected nonstatic data member of a base class, an access check applies in addition to those described earlier in clause 11.102) Except when forming a pointer to member (5.3.1), the access must be through a pointer to, reference to, or object of the derived class itself (or any class derived from that class) (5.2.5). 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).
And the example follows from the Standard (2003) itself as:
[Example: 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, even though naming class is B) 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) int B::* pmi_B = &B::i; // ill-formed int 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; // ill-formed p1->i = 2; // ill-formed p2->i = 3; // ill-formed } —end example]
Note in the above example fr()
is a friend function of D2
, mem()
is a member function of D2
, and g()
is neither a friend, nor a member function.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With