4

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?

4
  • same answer as for calling private method on another class. make it pubic or friend it or think again do you really need to call it? Commented May 27, 2014 at 23:28
  • Have you tried a friend class? Commented May 27, 2014 at 23:30
  • 1
    If this is an academic question, you can use friendship to resolve it. If this arises from a real application, you need to question your design. Figure out a better design that does not put you in this fix. Commented May 27, 2014 at 23:39
  • The problem of friend is modularity. B doesn't have to know what classes will subclass it and will use its protected functions. This is not truly a concreate question because I know that I could adopt a different desing. But I se no objections, in my case, about calling base class functions like this. Commented May 28, 2014 at 16:32

3 Answers 3

3

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks ! I find your solution quite clean because it doesn't need to modify anithing in the class hierarchy, unlike friend solution.
I am wondering if there is undefined (or at least unspecified) behavior in this. I would expect it because we are more or less calling a method of type D on an object of type B. On the other hand, I guess chances are high that this will always work as expected even if UB.
1

The better solution would be to declare a static protected function in Base that redirects the call to the private / protected function. This way, we don't break encapsulation because the designer of Base can make an explicit choice to allow all derived classes to call foo on each other, while avoiding to put foo into the public interface or explicitly turning all possible subclasses of Base into friends.

See my answer for the original question with code examples.

Comments

0

You could make class D a friend of class B:

class B {
friend class D;
protected:
    void f ();
};

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.