Department of Engineering

IT Services

C++: Virtuals and overloading

In the wxWidgets documentation I found the following

some GetXXX() methods may be overloaded (as, for example, wxWindow::GetSize or wxWindow::GetClientSize). In this case, the overloads are non-virtual because having multiple virtual functions with the same name results in a virtual function name hiding at the derived class level (in English, this means that the derived class has to override all overloaded variants if it overrides any of them). To allow overriding them in the derived class, wxWidgets uses a unique protected virtual DoGetXXX() method and all GetXXX() ones are forwarded to it, so overriding the former changes the behaviour of the latter

I think this merits expansion. Consider the following code -

#include <iostream>
using namespace std;

class base {
public:
  virtual void fun1() {cout << "base fun1 no arg" << endl; }
  virtual void fun1(int i) {cout << "base fun1 1 arg" << endl; }
};

class derived: public base  {
public:
  void fun1() {cout << "derived fun1 no arg" << endl; }
};

int main() {
  base b;
  b.fun1();
  b.fun1(7);

  derived d;
  d.fun1();
}

fun1 in the derived class overrides the one in the base class, so d.fun1() runs the derived version of fun1, as intended. The trouble is that adding

 d.fun1(7);

to the main function fails, because overriding one variant of fun1 in the derived class makes the base's other variants unavailable, which isn't helpful. An alternative approach is the following -

#include <iostream>
using namespace std;

class base {
public:
  void fun1() {dofun1(0); }
  void fun1(int i) {dofun1(i); }
protected:
  virtual void dofun1(int i) {cout << "base fun1, arg=" << i << endl; }
};

class derived: public base  {
public:
  void dofun1(int i) {cout << "derived fun1, arg=" << i << endl; }
};

int main() {
  base b;
  b.fun1();
  b.fun1(7);

  derived d;
  d.fun1();
  d.fun1(7);
}

Here all the fun1 variants in base eventually call the same function - dofun1. It's now possible to override just one function in the derived class and still have all of the fun1 calls working as intended.

Why use virtual? For the usual reasons - if the following code is appended to the main routine above

  base* pointer_to_b= &b;
  base* pointer_to_d= &d;
  pointer_to_b->fun1();
  pointer_to_d->fun1();

it will output what we usually want -

base fun1, arg=0
derived fun1, arg=0

i.e. even though both pointers are of type base *, using them doesn't mean that the base's functions are called. If you now remove "virtual" from the code above and recompile, you'll see that this behaviour (and others too) changes.