6

This is the code:

class TestA { protected: int test=12; public: TestA() { cout << "test a: " << test << endl; } ~TestA() { } }; class TestB : public TestA { public: TestB(TestA *testA) { cout << "test b: " << testA->test; } ~TestB() { } }; int main () { TestA *pTestA=new TestA(); TestB *pTestB=new TestB(pTestA); } 

I'm trying to access of a protected member using a pointer pointing to a TestA type object (thus, an instance of TestA). TestB is also derived from TestA

Why I can't access to it? Is it accessible only "within" the class where I need it? Not outside using pointer/direct declarations?

3
  • I am reopening this question as the answer mentioned here is better than the older duplicate: accessing a protected member of a base class in another subclass. Closing the other one. Commented Aug 2, 2016 at 10:25
  • Short answer: Because the standard says this is forbidden. Accordingly, standard compliant compilers will throw an error on it. YMMV, but I would actually call this a bug in the standard. Commented Aug 2, 2016 at 10:51
  • 2
    @cmaster (See the sample code in my answer) If it's allowed, it's possible to access the protected members through a pointer of type B* which points to an instance of D1 in member function of D2. But D1 and D2 are irrelevant in fact. It seems counterintuitive. Commented Aug 2, 2016 at 10:57

2 Answers 2

8

When public inherite from the base class, its protected members become the derived class' protect members, which could be accessed in derived class' member functions. But they could only be accessed through the derived class itself (and its derived classes), can't be accessed through the base class. So you can't access member test via pointer of TestA, but it'll be fine to access it via pointer of TestB.

The standard gives some illustrative samples for this. [class.protected]/1:

(Only keep a part of the example code)

An additional access check beyond those described earlier in Clause [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])114 As described earlier, access to a protected member is granted because the reference occurs in a friend or member of some class C. If the access is to form a pointer to member ([expr.unary.op]), the nested-name-specifier shall denote C or a class derived from C. All other accesses involve a (possibly implicit) object expression ([expr.ref]). In this case, the class of the object expression shall be C or a class derived from C. [ Example:

class B { protected: int i; }; class D1 : public B { }; class D2 : public B { void mem(B*,D1*); }; 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) } 

— end example ]

I'm not sure about your design's intent, making TestB friend of TestA would be a straightforward solution.

Sign up to request clarification or add additional context in comments.

3 Comments

This is one of the harder-to-justify (for me) access rules.
By the way, "When public inherite from the base class, its protected members become the derived class' protect members": Is that not true for protected inheritance as well? Or even private?
@PeterA.Schneider It's true for protected inheritance too, for private inheritance, will be "its protected members become the derived class' private members".
0

Concept of accessibility of class members by WORLD is applicable here. WORLD can access only public members of class irrespective of how they are created/derived.

Consider the example below:

class A { public: int public_i; protected: int protected_i; private: int private_i; public: A() { public_i = 10; protected_i = 20; private_i = 30; } }; class C : protected A { public: void Access(void) { cout << public_i << endl; cout << protected_i << endl; //cout << private_i << endl; // <- Not Allowed b'coz its private here } }; class D : private A { public: void Access(void) { cout << public_i << endl; cout << protected_i << endl; //cout << private_i << endl; // <- Not Allowed b'coz its private here } }; class B : public A { public: void Access(D *pd) { cout << public_i << endl; cout << protected_i << endl; //cout << private_i << endl; // <- Not Allowed b'coz its private here //pd is WORLD here //cout << pd->public_i << endl; // <- Not Allowed b'coz its private here since private inheritance of A by D //cout << pd->protected_i << endl; // <- Not Allowed b'coz its protected here //cout << pd->private_i << endl; // <- Not Allowed b'coz its private here } }; int main () { A objA; cout << objA.public_i << endl; //cout << objA.protected_i << endl; // <- Not Allowed b'coz its protected here //cout << objA.private_i << endl; // <- Not Allowed b'coz its private here B objB; cout << objB.public_i << endl; //cout << objB.protected_i << endl; // <- Not Allowed b'coz its protected here //cout << objB.private_i << endl; // <- Not Allowed b'coz its private here C objC; //cout << objC.public_i << endl; // <- Not Allowed b'coz its protected here //cout << objC.protected_i << endl; // <- Not Allowed b'coz its protected here //cout << objC.private_i << endl; // <- Not Allowed b'coz its private here D objD; //cout << objD.public_i << endl; // <- Not Allowed b'coz its private here //cout << objD.protected_i << endl; // <- Not Allowed b'coz its protected here //cout << objD.private_i << endl; // <- Not Allowed b'coz its private here //Outside class its all WORLD and WORLD can access only public members. //Objects and Pointers are WORLD. //Same thing is applicable when class members are accessed via pointers. B *pobjB; //pobjB is WORLD cout << pobjB->public_i << endl; //cout << pobjB->protected_i << endl; // <- Not Allowed b'coz its protected here //cout << pobjB->private_i << endl; // <- Not Allowed b'coz its private here objB.Access(&objD); objC.Access(); objD.Access(); return 0; } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.