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.
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.
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)
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