Thursday, July 28, 2011

Gotcha in C++ Function Overloading

Suppose we have this code.
#include <iostream>
using namespace std;

class Base {
public:
    virtual void doSomething(double a) {
        cout << "This is double from Base: " << a << endl;
    }
    virtual void doSomething(int a) {
        cout << "This is int from Base: " << a << endl;
    }
    virtual ~Base() {}
};

class Derived : public Base {
public:
    virtual void doSomething(double a) {
        cout << "This is double from Derived: " << a << endl;
    }
    virtual ~Derived() {}
};

int main() {
    Derived d;

    int i = 2;
    double j = 0.1;
    d.doSomething(i);
    d.doSomething(j);

    return 0;
}
We would expect the output to be:
This is int from Base: 2
This is double from Derived: 0.1

Strangely, the output is:
This is double from Derived: 2
This is double from Derived: 0.1

The way overload resolution works in C++ is that the compiler will first search for function doSomething() inside the Derived class. If it finds it, it will stop there; otherwise it will look the one in the Base class for a matching function. To solve this problem, we need to add using Base::doSomething in order let it participate in the overload resolution.
#include <iostream>
using namespace std;

class Base {
public:
    virtual void doSomething(double a) {
        cout << "This is double from Base: " << a << endl;
    }
    virtual void doSomething(int a) {
        cout << "This is int from Base: " << a << endl;
    }
    virtual ~Base() {}
};

class Derived : public Base {
public:
    virtual void doSomething(double a) {
        cout << "This is double from Derived: " << a << endl;
    }
    using Base::doSomething; 
    virtual ~Derived() {}
};

int main() {
    Derived d;

    int i = 2;
    double j = 0.1;
    d.doSomething(i);
    d.doSomething(j);

    return 0;
}

The output is:
This is int from Base: 2
This is double from Derived: 0.1

No comments:

Post a Comment