1

Say class B derives from class A. That both declare f(). f is protected. Hence f will only be called inside A and inside B. Does f() need to be declared virtual?

Or rather: say C derives from B derives from A. B and A declare protected non-virtual f(). Will a call to f() in C and B resolve to B::f() and in A to A::f()?

In that case, should we always avoid virtual for protected members to have static resolution? Is this done automatically? Thanks!

Cookie
  • 12,004
  • 13
  • 54
  • 83

4 Answers4

2

As long as the call to f() is done in a function derived from A (and not overloaded/reimplemented in B or C), the this pointer resolves to A* and therefore A::f() is called. So no, you still need a virtual function in this case.

Christian Rau
  • 45,360
  • 10
  • 108
  • 185
1

Declaring your protected method virtual is necessary when you want polymorphic behaviour (an example to this is the Template Method pattern), and is to be avoided when you don't. However, in the latter case you should not shadow the function with another function having the same signature in the subclass, otherwise you get puzzling behaviour (like the one you describe in your 2nd paragraph) which opens up the possibility for subtle bugs.

Péter Török
  • 114,404
  • 31
  • 268
  • 329
  • What is polymorphic behaviour in this case though? Isn't that assuming to have a pointer to a base class? Doesn't this then by definition require public function access? – Cookie Sep 12 '11 at 10:35
  • @Cookie No. In every function, that you call on A (from the outside) or that you haven't reimplemented/overloaded in C or B, `this` is a pointer to A, so only the A methods are known and if the method called is not virtual it is not resolved at runtime and you get the A method. – Christian Rau Sep 12 '11 at 10:38
  • @Cookie, no, it doesn't require public access. Consider a public method in `A` calling a `protected virtual` method declared in `A` and overridden in different subclasses. You get polymorphic behaviour via a `protected` method. See the reference to *Template Method* above for more details. – Péter Török Sep 12 '11 at 10:38
0

I am a bit rusty on my C++ but I would say that "static resolution" would only be guaranteed when you declare the method private and thus you need virtual together with protected in your scenario...

Yahia
  • 69,653
  • 9
  • 115
  • 144
  • 1
    You can actually have [private virtual functions](http://stackoverflow.com/questions/2170688/private-virtual-method-in-c) in C++, and they will be dynamically binded. In Java and C#, IIRC, privates are indeed not overrideable, hence statically binded. – Eran Sep 12 '11 at 11:39
0

So:

class A {
public:
  void f() { std::cout << "A::f\n"; }
};

class B : public A {
public:
  void f() { std::cout << "B::f\n"; }
};

As long as the compiler knows that an object is actually a B, it will call f() in B. But, this is not always the case:

void callF(A* a)
{
  a->f();
}

B b;
callF(&b);  // prints A::f

If you want functions like callF to call the correct f() function, make it virtual. Generally, you make functions virtual if it makes sense to override them in a descendant class. This is often the case for protected functions.

Frederik Slijkerman
  • 6,471
  • 28
  • 39