We can find here and here the explanation of why we can't call protected method of base class on base object from method in derived class, like in this code :
class B {
protected:
void f ();
};
class D : public B {
public:
void g (B* other) {
other->f(); /* Error: B::f() is protected */
}
};
But are there any solutions? What if we really want to call this base method on this object? After all, there wouldn't be any problem doing this, we can ensure that other
is really a B
?
Note: The straight forward (and recommended) way to enable something as this is to make the inherited class a friend
of the base class; this means that it will have access to it's protected
and private
parts.
I wanna bend the rules a little
So you have decided that the rules set forth by the Standard are annoying, you want to do whatever you want, when you want, and the way you want it! Rules are meant to be broken, etc etc.
class B {
protected:
void f ();
};
class D : public B {
public:
void g (B * other) {
(other->*&D::f) (); // legal
}
};
How does this, legal and fully functional, hack work?
Even though the Standard says that we are not allowed to inspect B::f
from within D
, we are of course allowed to look at D::f
; which is the same (inherited) thing, since we didn't declare another f
inside D
.
Our hack concists of taking the address of D::f
, relying on the fact that the type of it really is a pointer to a member function within B
, and using this address to call the function upon other
.
Another (semantically) equivalent way to write the snippet:
void (B::*hack)() = &D::f; (other->*hack) ();
Note: Technically we are not diving into the protected contents of B
, we are merely relying on the fact that the contents accessed through D::f
happens to be the same as the one in B::f
. We are still playing by the rules set forth by the Standard, it's just that we are somewhat abusing them.