Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I access a protected member from an instance of a base class? [duplicate]

Tags:

c++

Let's say I have this code:

class foo{
  protected:
  int a;
};

class bar : public foo {
  public:
  void copy_a_from_foo(foo& o){
    a = o.a; // Error
  }
  void copy_a_from_bar(bar& o){
    a = o.a; // OK
  }
};

int main(){
  bar x;
  foo y;
  bar z;
  x.copy_a_from_foo(y);
  x.copy_a_from_bar(z);
}

here class bar has no problems accessing the protected member a from another instance of the same class, but when I try to do the same with an instance of the base class foo, the compiler gives me an error saying that a is protected. What does the standard has to say about this?

error is

prog.cpp: In member function 'void bar::copy_a_from_foo(foo&)':
prog.cpp:3:7: error: 'int foo::a' is protected
   int a;
       ^
prog.cpp:9:11: error: within this context
     a = o.a;

P.S.: I had a look at this question, but it's not quite the same: I'm trying to access the protected member from within the derived class.

like image 754
Cássio Renan Avatar asked Apr 03 '15 21:04

Cássio Renan


2 Answers

You can access the protected members of a base class only through a pointer or reference to an object of the derived type.

If you change

void copy_a_from_bar(bar& o){
  a = o.a;
}

to

void copy_a_from_bar(bar& o){
  foo& foo_ref = o;
  a = o.a;        // OK. Accessing it through `bar&`
  a = foo_ref.a;  // Not OK. Accessing it through `foo&`
}

you will see the same error.

This SO answer gives an indication of why allowing access to the protected members of the base class will be a potential breach of the protected status of the base class members.

Say you have:

class baz : public foo
{
   void update_a(foo& f)
   {
      f.a = 20;
   }
};

and use:

bar x;
baz z;
z.update_a(x);

If this were allowed, baz will be able to change the values of members of bar. That is not good.

like image 65
R Sahu Avatar answered Sep 20 '22 11:09

R Sahu


protected means it can be accessed as a member in derived classes. It does not grant derived classes unrestricted access.

The reasoning (I'd presume) is so that the derived class can modify the base type in order to maintain the derived type's own contracts. However, it has no need of accessing the protected members of other derived classes, because that could invalidate their contracts.

A contract is a promise about the states of the members. Some example contracts you might be familiar with are in the internals of string: the size contains the length of the string in the buffer, and buffer[size] contains a null (There's a ton of technicalities here, but they're unimportant). Also that the buffer always points to null or a valid null-terminated string, with unique ownership. The string class works hard to make sure that, no matter what, all of these things are true. (string doesn't actually have any of these contracts because it's members are private, this is just an example)

like image 30
Mooing Duck Avatar answered Sep 16 '22 11:09

Mooing Duck