0

Perhaps my knowledge of inheritance and polymorphism isn't what I thought it was. Can anyone shed some light?

Setup (trivialization of problem):

class X {
};

class Y {
};

class Base {
  public:
    void f( X* ) {}
};

class Child: public Base {
  public:
    void f( Y* ) {}
};

Question: This should work, right?

int main( void ) {
  X* x = new X();
  Y* y = new Y();
  Child* c = new Child();
  c->f( x );
  c->f( y );
  return 0;
}

I get errors (GCC 4.4) to the tune of:

`no matching function for call to 'Child::f(X*&)'`
`note: candidates are: void Child::f(Y*)`
AnT
  • 302,239
  • 39
  • 506
  • 752
Chris Tonkinson
  • 13,033
  • 13
  • 55
  • 88
  • 12
    Name hiding. This question gets asked like 3 times a day. See the FAQ http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.9 – AnT Dec 11 '09 at 18:32
  • Did you mean for your two classes to be called A and B? – Dave Dec 11 '09 at 18:33
  • Perhaps I'm misreading, but are you sure that the arguments to f should be A and B? – tloach Dec 11 '09 at 18:33
  • His error message shows that he has no `A` and `B` in his real code. It is just a typo. I corrected the source. – AnT Dec 11 '09 at 18:35
  • Thanks, @AndreyT - I had A, B, C, and D originally but it was too confusing. – Chris Tonkinson Dec 11 '09 at 18:39
  • possible duplicate of [Why does an overridden function in the derived class hide other overloads of the base class?](http://stackoverflow.com/questions/1628768/why-does-an-overridden-function-in-the-derived-class-hide-other-overloads-of-the) – Mooing Duck Feb 03 '14 at 17:28

3 Answers3

9

The virtual keyword will not help you here.

Your base class Base::f is being hidden by your derived type. You need to do the following:

class Child: public Base {
  public:
    using Base::f;
    void f( Y* ) {}
};

Parashift goes into more detail.

Brian R. Bondy
  • 327,498
  • 120
  • 583
  • 623
  • Okay, I didn't know you could do 'using' in a class like that - thanks. At any rate, I'm well familiar with the concept of name hiding - but is it really **ONLY** based upon function name, and not the entire signature? – Chris Tonkinson Dec 11 '09 at 18:49
  • 2
    Yes, the look-up by name happens before overload resolution, thus `Base::f` isn't considered for overloads without pulling them in explicitly. – Georg Fritzsche Dec 11 '09 at 19:41
2

Your derived class' f() hides the base class' f(). You can prevent this by explicitly bringing Base::f() into the derived class' scope:

class Child: public Base {
  public:
    using Base::f;
    void f( Y* ) {}
};
sbi
  • 212,637
  • 45
  • 247
  • 432
0

It was already answered at:

Why does an overridden function in the derived class hide other overloads of the base class?

When you declare a method on a derived class, it hides any method with the same name from the base class.

Community
  • 1
  • 1
J. Calleja
  • 4,785
  • 2
  • 30
  • 51