Jaebum
Jaebum

Reputation: 1570

C++ simple inheritance problem

#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

Answers (3)

Jon
Jon

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

djeidot
djeidot

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 friending class B.

Or by using a pointer to B instead of a pointer to A, as Jon noted.

Upvotes: 2

Chad La Guardia
Chad La Guardia

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

Related Questions