Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot access protected member [duplicate]

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?
}
like image 405
parc84 Avatar asked Sep 19 '11 19:09

parc84


People also ask

How do you access protected member functions?

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.

Can protected members be accessed by objects?

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.

How to access protected variable in c++?

The class member declared as Protected are inaccessible outside the class but they can be accessed by any subclass(derived class) of that class.

Are protected members inherited?

prot is inherited as protected.

What is a protected variable c++?

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.


3 Answers

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
}
like image 102
Kerrek SB Avatar answered Nov 09 '22 05:11

Kerrek SB


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.

like image 41
David Hammen Avatar answered Nov 09 '22 06:11

David Hammen


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
}
like image 1
Robᵩ Avatar answered Nov 09 '22 05:11

Robᵩ