I ran into an error yesterday and, while it\'s easy to get around, I wanted to make sure that I\'m understanding C++ right.
I have a base class with a protected member:
class Base
{
protected:
int b;
public:
void DoSomething(const Base& that)
{
b+=that.b;
}
};
This compiles and works just fine. Now I extend Base but still want to use b:
class Derived : public Base
{
protected:
int d;
public:
void DoSomething(const Base& that)
{
b+=that.b;
d=0;
}
};
Note that in this case DoSomething
is still taking a reference to a Base
, not Derived
. I would expect that I can still have access to that.b
inside of Derived
, but I get a cannot access protected member
error (MSVC 8.0 - haven\'t tried gcc yet).
Obviously, adding a public getter on b
solved the problem, but I was wondering why I couldn\'t have access directly to b
. I though that when you use public inheritance the protected variables are still visible to the derived class.
You can only access protected members in instances of your type (or derived from your type).
You cannot access protected members of an instance of a parent or cousin type.
In your case, the Derived
class can only access the b
member of a Derived
instance, not of a different Base
instance.
Changing the constructor to take a Derived
instance will also solve the problem.
You have access to the protected members of Derived
, but not those of Base
(even if the only reason it\'s a protected member of Derived
is because it\'s inherited from Base
)
As mentioned, it\'s just the way the language works.
Another solution is to exploit the inheritance and pass to the parent method:
class Derived : public Base
{
protected:
int d;
public:
void DoSomething(const Base& that)
{
Base::DoSomething(that);
d=0;
}
};
protected
members can be accessed:
- through
this
pointer
- or to the same type protected members even if declared in base
- or from friend classes, functions
To solve your case you can use one of last two options.
Accept Derived in Derived::DoSomething or declare Derived friend
to Base:
class Derived;
class Base
{
friend class Derived;
protected:
int b;
public:
void DoSomething(const Base& that)
{
b+=that.b;
}
};
class Derived : public Base
{
protected:
int d;
public:
void DoSomething(const Base& that)
{
b+=that.b;
d=0;
}
};
You may also consider public getters in some cases.
class Derived : public Base
{
protected:
int d;
public:
void DoSomething()
{
b+=this->b;
d=0;
}
};
//this will work
You can try with static_cast< const Derived*>(pBase)->protected_member ...
class Base
{
protected:
int b;
public:
...
};
class Derived : public Base
{
protected:
int d;
public:
void DoSomething(const Base* that)
{
b += static_cast<const Derived*>(that)->b;
d=0;
}
};
Use this
pointer to access protected members
class Derived : public Base
{
protected:
int d;
public:
void DoSomething(const Base& that)
{
this->b+=that.b;
d=0;
}
};