Why does C++ overload resolution not look at base class methods when derived class methods are not viable?

Viewed 127

Example that fails to compile:

class A{
 public:
  int f(int a) {return a;}
};

class B: public A {
 public:
  int f(int a, int b) {return a + b;}
};

int calculation(int num) {
    B b;
    return b.f(num);
}

At the call site b.f(num), gcc gives the following error message:

error: no matching function for call to B::f(int&)

The base class has a viable candidate, but for some reason the compiler wouldn't consider it.

If I re-write the call as b.A::f(num), then it works fine. I don't understand why the A:: is necessary. How come A::f is not considered as a viable candidate by the overload resolution logic for the b.f?

2 Answers

The issue has nothing to do with overload resolution, but name lookup, which is performed before overload resolution. In unqualified name lookup, when the name f is found in the scope of class B, name lookup stops; the further scope including class A won't be examined, A::f won't be found at all. As the result only B::f is put in overload set then overload resolution is performed and fails to find the appropriate function.

name lookup examines the scopes as described below, until it finds at least one declaration of any kind, at which time the lookup stops and no further scopes are examined.

Because B::f hides A::f.

You need to explicitly pull in A::f into the scope of B:

class B : public A
{
public:
    using A::f;

    // ...
};
Related