Possible Duplicate:
cannot call base class protected functions?
I don't understand the following, when Derived
inherits from Base
, it gets access to its protected members which can be accessed through Derived functions. But if, Base
class tries to access its own members from Derived
class (which itself allows access to Base
), it doesn't get access, why?
class Base {
protected:
int x;
};
class Derived : Base {
public:
void foo(Base* b);
};
void Derived::foo(Base* b) {
b->x = 2; // cannot access protected member,
// though Derived inherits from Base, why?
}
Protected members in a class are similar to private members as they cannot be accessed from outside the class. But they can be accessed by derived classes or child classes while private members cannot.
Protected members that are not declared as static are accessible to friends and member functions in a derived class only through a pointer to, reference to, or object of the derived class.
The class member declared as Protected are inaccessible outside the class but they can be accessed by any subclass(derived class) of that class.
prot is inherited as protected.
A protected member variable or function is very similar to a private member but it provided one additional benefit that they can be accessed in child classes which are called derived classes. You will learn derived classes and inheritance in next chapter.
A common misunderstanding.
Inside Derived::foo()
, you can access protected base members of objects of class Derived
. However, *b
is not of type Derived
. Rather, it is of type Base
, and so it does not have anything to do with your class.
It's a different matter if you take a Derived*
as an argument -- then you will indeed have access to protected base members.
Let's spell it out:
struct Derived;
struct Base
{
int f(Derived *);
protected:
int x;
private:
int y;
};
struct Derived : public Base
{
int g(Base *);
int h(Derived *);
};
int Derived::g(Base * b)
{
return b->x; // error, protected member of unrelated class
return b->y; // error, private member of different class
}
int Derived::h(Derived * d)
{
return d->x; // OK, protected base member accessible in derived class
return d->y; // error, private member of different class
}
int Base::f(Derived * d)
{
return d->x; // OK, d converts to Base*
return d->y; // OK, ditto
}
You ran smack dab into a special rule in the standard:
11.5 Protected member access
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, *the access must be through a pointer to, reference to, or object of the derived class itself (or any class derived from that class).
One reason for this addition access check is with regard to the behaviors of those base class protected members. Since the members are protected, a different derived class can add semantics to or even make wholesale changes in the meaning of those derived members. (This is one of the reasons why protected data is rather dangerous.) Because your class is oblivious to these additions / modifications to the base class semantics made in other derived classes, the best thing to do is to preclude access to base class members when the access would be through the base class.
To provide concrete example of what others are saying:
class Base {
protected:
int x;
};
class Derived : Base {
public:
void foo(Derived*, Base*);
};
int main() {
Base fiddle;
Derived fast, furious;
fast.foo(&furious, &fiddle);
}
void Derived::foo(Derived *d, Base* b) {
x = 1; // Legal, updates fast.x
this->x = 2; // Legal, updates fast.x
d->x = 3; // Legal, updates furious.x
b->x = 4; // Error, would have updated fiddle.x
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With