I get a compile error, which I'm slightly confused about. This is on VS2003.
error C2248: 'A::y' : cannot access protected member declared in class 'A'
class A
{
public:
A() : x(0), y(0) {}
protected:
int x;
int y;
};
class B : public A
{
public:
B() : A(), z(0) {}
B(const A& item) : A(), z(1) { x = item.y;}
private:
int z;
};
The problem is with x = item.y;
The access is specified as protected. Why doesn't the constructor of class B have access to A::y?
IBM's documentation summarizes it best:
Thus, using your example above as the basis:
It's because of this:
If that were legal, you could do this:
And you'd be calling a
protected
member of A from B, which isn't allowed.The other answers explain the reasoning behind preventing your
B
object from accessing the protected parts ofA
in your example, even thoughB
'is-a'A
. Of course, the easiest way to fix this problem is to make the parts ofA you want access to
public` or have publicly accessible accessor methods.However you might decide that's inappropriate (or you might not have control over the definition of
A
). Here are some suggestions to let you work around the problem, in increasing order of subvertingA
's access control. Note that all of these workarounds assume thatclass A
is copy-constructable.In the first case, you simply use the copy constructor for
A
to set up an initial state for that part of theB
object, then fix it up afterward:I find that incredibly confusing and probably very error prone (assuming that we want the
A
sub-object in theB
object to be different than theA
object being passed to the constructor - an unusual situation, but it's what was given in the problem). However, the fact that it can be done gives some justification for the more subversive examples that follow...The next example creates a temporary
B
object that has an exact duplicate of theA
object we want access to. We can then use the temporaryB
object to get to the items that were protected:I find that solution to be a bit less confusing than the first, but it's still confusing (in my opinion). Having a bastard version of of B object just to get to the parts of the A object we want is odd.
We can do something about that by creating a special proxy for
A
objects that gives the access we want. Note that this is the 'most subversive' workaround because it's something that any class could do to get to protected parts ofA
, even if they aren't sub-classes ofA
themselves. In the case of theB
class, there's some legitimacy to getting to the protected parts ofA
objects, sinceB
is-aA
, and as we've already seen there are workarounds that let us get access that use only rights thatclass B
already has, so I consider this a cleaner version of those workarounds inclass B
's case.