The following code produces a compiler error:
'BaseTest::_protMember' : cannot access protected member declared in class 'BaseTest'
Why can't I access the member variable _protMember
in my class SubTest
even though it is protected?
class BaseTest
{
public:
BaseTest(){};
BaseTest(int prot)
{
_protMember = prot;
};
protected:
int _protMember;
};
class SubTest : public BaseTest
{
// followup question
SubTest(const SubTest &subTest)
{
_protMember = subTest._protMember; // this line compiles without error
};
SubTest(const BaseTest &baseTest)
{
_protMember = baseTest._protMember; // this line produces the error
};
};
Followup question:
Why is it, that in the added copy constructor I can access protected members of another instance?
You can only access protected
members from your own base class instance... not one provided to you as a parameter. It's all about OO encapsulation really. Without this restriction, the object under construction could invalidate invariants of the baseTest&
parameter.
Put another way, your SubTest
may decide on a use for a protected
member that conflicts with the usage made of the same member by another BaseTest
-derived class (say SubTest2 : BaseTest
). If your SubTest
code was allowed to fiddle with the other object's data, it could invalidate the invariants in a SubTest2
object, or get some values out that were - in the intended encapsulation - only meant to be exposed to SubTest2
and (optionally - see below) SubTest2
derivatives.
Followup question: Why is it, that in the added copy constructor I can access protected members of another instance?
SubTest(const SubTest& x); // can access x._protMember
SubTest(const BaseTest& x); // cannot access x._protMember
The same insights above explain why this is allowed: the copy constructor gets a SubTest&
rather than just any old object derived from BaseTest
, and this constructor is clearly within the SubTest
abstraction. The SubTest
coder is assumed to be conversant with the intended design/encapsulation SubTest
provides, and the copy constructor is given access to bypass and enforce post-conditions/invariants on the other SubTest&
object too. (You are copying from an object that might itself have been copy-constructed by the very same function, so protecting it when on the "*this
" side but not the parameter-by-ref side isn't much protection at all, even ignoring all the sound reasons you may want/need that access).
It is possible that a SubTest
-derived object will be accidentally passed to the SubTest
copy constructor ("slicing"), but even for that scenario the SubTest&
class can control whether the further-derived object could have been doing anything unexpected with _protMember
- adding a private
using BaseTest::_protMember;
statement if it wants to "finalise" access to _protMember
and forbid any derived classes from using it.
You can access protected
members only in the class instance. That is :
class SubTest : public BaseTest
{
SubTest(const BaseTest &baseTest)
{
_protMember = baseTest._protMember;
// ^^^^^^^^^^^ Is good because you are in the instance of its class
_protMember = baseTest._protMember;
// ^^^^^^^^^^^^^^^^^^^^^ Produce error because you are not in the baseTest instance.
};
// followup question
SubTest(const SubTest &subTest)
{
_protMember = subTest._protMember;
// Compile because access modifiers work on class level, and not on object level.
};
};
EDIT for the followup :
The access modifiers work on class level, and not on object level.
That is, two objects of the same class can access each others private members.
This is my source : Why can I access private variables in the copy constructor?
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