Why can't I access the protected member variable of the base class passed to the function as an argument?

This answer seems like it should work, so why does my example throw a compiler error:

class Class1 { protected: long m_memberVar; }; class SubClass1: public Class1 { public: void PrintMember(Class1 memberToPrintFrom) { Console::Write("{0}", memberToPrintFrom.m_memberVar); // <-- Compiler error: error C2248: 'BaseClassMemberAccess::Class1::m_memberVar' : cannot access protected member declared in class 'BaseClassMemberAccess::Class1' } }; 

[Edit] - changed the subclass to the public inheritance of Need4Sleep, but it does not make any difference.

+5
c ++ inheritance
source share
3 answers

In this answer, I assume that you used public inheritance in your code (which was missing from the question).


[C++11: 11.2/1]: If a class is declared a base class (section 10) for another class using the public access specifier , members of the public base class are available as public members of the derived class and protected members of the base class are available as protected members of the derived class . If a class is declared a base class for another class using the protected access specifier, members of the base class public and protected are available as members of the protected derived class. If a class is declared a base class for another class using the private access specifier, public and protected members of the base class are available as private members of the derived class.

This applies when you are accessing a member of the same object.

However, a bit of the curiosity of protected member access, in order to access the protected element of another object, it must be located in a definition of the same type or a more derived type; in your case, it is in a less derived type (i.e. base):

[C++11: 11.4/1]: optional outside access control described in section 11 above applies when a non-static data member or non-static member function is a protected member of its naming class (11.2). As described above, access to a protected member is granted because the link is found in a friend or member of some class C If the access consists in forming a pointer to a member (5.3.1), the sub-name specifier should denote C or a class derived from C All other calls include an (possibly implicit) expression of the object (5.2.5). In this case, the class of the expression of the object must be C or a class derived from C

So you will need to run this code from a member function of Class1 .

Bjarne mentions this in his book The C ++ Programming Language (Sp. Ed.) On page 404:

A derived class can access protected members of the base class only for objects of its own type [...] This prevents subtle errors that would otherwise occur when one derived class distorted data belonging to other derived classes.

+11
source share

Protected members of the base class can access the derived class only through its self (this) or through another object of the same class, but not in general terms through the base class. This is access, and the goal is that the use of a member is considered limited by the details of the implementation of the class, and since your class deals with the base class, it will not know the value of the member in this particular case.

There is a workaround that you can use to gain access, which should provide a secure getter and setter in the base class, often static, that will retrieve it or install it for you.

 class Class1 { protected: long m_memberVar; // could even be private static long getMemberVar( Class1 const& inst ) { return inst.m_memberVar; } static long setMemberVar( Class1 & inst, long val ) { inst.m_memberVar = val; } }; 

And now derived classes (but not general classes) can use the getter and setter methods.

+1
source share

You can also take advantage of the fact that a derived object can be converted to a type of a base object and that the object can access protected and private members of any object of its own type. If the base object has an assignment operator that can guarantee that all the desired members are correctly copied, you can do something like this:

 class Class1 { protected: long m_memberVar; }; class SubClass1 : public Class1 { public: void PrintMember(Class1 memberToPrintFrom) { SubClass1 tmpSC; auto tmpC1 = dynamic_cast<Class1*>(&tmpSC); *tmpC1 = memberToPrintFrom; cout << tmpSC.m_memberVar << endl; } }; 

This is inefficient, but allows you to access the base class without the need to add functions to the base class. This is the use of a slice of objects to replace the base part of a temporary derived object with the transferred values ​​of the base object.

+1
source share

All Articles