6

I have a baseclass that has two functions of same name but with different signatures in a 2-level inheritance.

struct A {
    virtual void f(int) { }
    virtual void f(int, int) { };
    virtual void f1(int) { }
};

struct B: public A { };

struct C: public B {
  void f(int, int) { }
  void f1(int) { }
};

int main() {
 C obj;
 obj.f1(0);
 obj.f(0,0);

 obj.f(0);    // (1) cannot be found
 obj.B::f(0); // (2) works

}

I would have expected my compiler (gcc-4.3.2) to find the correct definition at (1), but I get

g++     main.cpp   -o main
main.cpp: In function 'int main()':
main.cpp:20: error: no matching function for call to 'C::f(int)'
main.cpp:10: note: candidates are: virtual void C::f(int, int)
distcc[2200] ERROR: compile main.cpp on localhost failed
make: *** [main] Error 1

(2) on the other hand works.

What do I need to fix to make (1) work in general?

Benjamin Bannier
  • 55,163
  • 11
  • 60
  • 80

3 Answers3

6

Write using A::f inside the definition of C.

You are a victim of name hiding! void C::f(int, int) hides void A::f(int), just because.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
5

The C++ name lookup rules have it so that if a name is redefined in one scope, all overloads of that name are hidden.

But you can use using to help. Like this:

class A {
    public:
    int f(int x) { cout << "A::f 1\n"; }
    int f(int x, int y) { cout << "A::f 2\n"; }
};

class B : public A {
    public:
    using A::f;
    int f(int x) { cout << "B::f 1\n"; }
};

int main()
{
    B b;

    b.f(27, 34);

    return 0;
}

Output is:

A::f 2
Zan Lynx
  • 53,022
  • 10
  • 79
  • 131
3

The short answer to "why" is "because that's how overloading works." You are hiding the f(int) overload in C. The longer answer is much longer.

You can un-hide it by doing this:

struct C: public B {
  using A::f;
  void f(int, int) { }
  void f1(int) { }
};
John Dibling
  • 99,718
  • 31
  • 186
  • 324