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?
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. $11.4/1 Protected member access [class.protected]:
(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.
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;
}