I am confused: I thought protected data was read/writable by the children of a given class in C++.
The below snippet fails to compile in MS Compiler
class A
{
protected:
int data;
};
class B : public A
{
public:
B(A &a)
{
data = a.data;
}
};
int main()
{
A a;
B b = a;
return 0;
}
Error Message:
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.
demoFail.cpp
demoFail.cpp(12) : error C2248: 'A::data' : cannot access protected member declared in class 'A'
demoFail.cpp(4) : see declaration of 'A::data'
demoFail.cpp(2) : see declaration of 'A'
What am I doing wrong?
According to TC++PL, pg 404:
A derived class can access a base class’ protected members only for objects of its own type.... This prevents subtle errors that would otherwise occur when one derived class corrupts data belonging to other derived classes.
Of course, here's an easy way to fix this for your case:
class A
{
protected:
int data;
};
class B : public A
{
public:
B(const A &a)
: A(a)
{
}
};
int main()
{
A a;
B b = a;
return 0;
}
The C++ Standard says about protected non-static members at 11.5/1
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 (5.3.1), the access must be through a pointer to, reference to, or object of the derived class itself (or any class derived from that class) (5.2.5). If the access is to form a pointer to member, the nested-name-specifier shall name the derived class (or any class derived from that class).
In addition to fixing things mentioned earlier by others (constructor of B
is private), i think rlbond's way will do it fine. However, a direct consequence of the above paragraph of the Standard is that the following is possible using a member pointer, which arguably is a hole in the type system, of course
class B : public A {
public:
B(A &a){
int A::*dataptr = &B::data;
data = a.*dataptr;
}
};
Of course, this code is not recommended to do, but shows that you can access it, if you really need to (I've seen this way being used for printing out a std::stack
, std::queue
, std::priority_queue
by accessing its protected container member c
)
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