Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does that have to do with function overloading?

This is basically a copy from the example given in Item 21. Overriding Virtual Functions in Herb Sutter's book Exceptional C++.

#include <iostream>
#include <complex>
using namespace std;
class Base
{
public:
    virtual void f(int);
    virtual void f(double);
    virtual ~Base() {};
};

void Base::f(int) { cout << "Base::f(int)" << endl; }
void Base::f( double ) { cout << "Base::f(double)" << endl; }

class Derived: public Base {
public:
    void f(complex<double>);
};

void Derived::f(complex<double>) { cout << "Derived::f(complex)" << endl; }

int main()
{
    Base* pb = new Derived;
    pb->f(1.0);
    delete pb;
}

The code prints Base::f(double) and I have no problems with that. But I couldn't understand the explanation given by the author on the top of page 122 (emphasis is mine):

Interestingly, even though the Base* pb is pointing to a Derived object, this calls Base::f( double ), because overload resolution is done on the static type (here Base), not the dynamic type (here Derived).

My understanding is that the call pb->f(1.0) is a virtual call and Base::f(double) is the final overrider for f(double) in Derived. What does that have to do with function overloading?

like image 341
Wake up Brazil Avatar asked May 19 '14 13:05

Wake up Brazil


1 Answers

The delicate part here is that virtual methods are a mechanism to dispatch the function call, while overloading is a feature that affects the resolution of the call.

That is, for any call the compiler needs to figure out which method should be called (resolve it); afterwards, and in a logically distinct operation, it needs to generate code that calls the correct implementation of that method (dispatch it).

From the definitions of Base and Derived given above we can easily reason that if f(double) is called on a Base* then the call should be dispatched to any derived override (if applicable) in preference to the base implementation. But answering that is answering a question totally different than

When the source says pb->f(1.0), which of the methods named f should be used to resolve the method call?

As Sutter explains, the spec says that when resolving the call the compiler will look at the methods named f declared on the static type pointed to by pb; in this case, the static type is Base* so overloads (not overrides!) declared on Derived will not be considered at all. However, if the method that the call resolves to is virtual then the possible implementation provided on Derived will be used as expected.

like image 90
Jon Avatar answered Oct 08 '22 23:10

Jon