Reputation: 1570
#include <iostream>
using namespace std;
class A
{
protected:
int a;
};
class B : public A
{
public:
int func(A* p)
{
cout << p->a;
}
};
I really cannot understand why I cant access to 'a' by 'p->a'.
Is there anyway to access p's member 'a' in class B, without changing 'protected' to 'public'?
Upvotes: 5
Views: 172
Reputation: 437396
On this topic, the C++03 standard states (emphasis mine):
11.5 Protected member access
1 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. 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).
What you are doing here, however, is trying to access through a pointer to the base class, which is illegal. If you change the signature to
int func(B* p) // instead of A*
you will find that it now compiles normally.
This is also the reason why you can access a
without trouble from inside class B
: the access is made through the implicit pointer this
, which is of type B*
(the derived class again). If you tried this:
A* parent = static_cast<A*>(this);
int x = parent->a; // Does not compile!
You would find that it won't compile, for the very same reason.
The converse also applies: if you downcast the pointer p
to a B*
you can access the protected
member just fine:
class A
{
public:
// Added virtual destructor so that the class acquires a vptr,
// making dynamic_cast possible.
virtual ~A() {};
protected:
int a;
};
class B : public A
{
public:
int func(A* p)
{
// Now if we downcast p to B* we can access a just fine
// Of course if p does not actually point to a B, the
// program will have undefined behavior
int x = dynamic_cast<B*>(p)->a;
}
};
Upvotes: 10
Reputation: 4642
Using p->a
would only let you access public variables of A. Since a
is a protected variable, you should use cout << a
, since a
is inherited in class B.
I think you could use cout << p->a
by friend
ing class B.
Or by using a pointer to B
instead of a pointer to A
, as Jon noted.
Upvotes: 2
Reputation: 5164
Ahh, this is a good question. First, let me start off by saying B
is NOT a friend of A
, and therefore does not have access to A
's privates (or protected's) through an "A" view of the object. Even though we are in the scope of class B
, we cannot just go around looking at A
's privates (or protected's).
HOWEVER, B does have an a
. And it does have access to it, because it is declared a protected member of A
. But the only way to see int a
inside of a B
, is to get it from a B
view of an object.
Upvotes: 1