Overriding a Base's Overloaded Function in C++ [duplicate]
Asked Answered
N

3

56

Possible Duplicate:
C++ overload resolution

I ran into a problem where after my class overrode a function of its base class, all of the overloaded versions of the functions were then hidden. Is this by design or am I just doing something wrong?

Ex.

class foo
{
  public:
    foo(void);
    ~foo(void);
    virtual void a(int);
    virtual void a(double);
};

class bar : public foo 
{
  public:
    bar(void);
    ~bar(void);
    void a(int);
};

the following would then give a compile error saying there is no a(double) function in bar.

main() 
{
  double i = 0.0;
  bar b;
  b.a(i);
}
Noctule answered 20/5, 2009 at 14:24 Comment(4)
It would help if you posted (if possible) actual code. The code you posted is missing some details, like semicolons after class definitions and the return type for a in bar...Maitland
I cannot post the actual code. I added the details into the post, this wasn't really meant as an exercise in syntax.Noctule
https://mcmap.net/q/112312/-c-overload-resolution-duplicateKory
I tried to compile this code on my computer, no error, "b.a(i)" calls "void a(int)" function in class bar, the 0.0 is converted into 0.Methodical
R
85

In class bar, add

using foo::a;

This is a common 'gotcha' in C++. Once a name match is found in the a class scope, it doesn't look further up the inheritance tree for overloads. By specifying the 'using' declaration, you bring all of the overloads of 'a' from 'foo' into the scope of 'bar'. Then overloading works properly.

Keep in mind that if there is existing code using the 'foo' class, its meaning could be changed by the additional overloads. Or the additional overloads could introduce ambiguity and and the code will fail to compile. This is pointed out in James Hopkin's answer.

Ravenous answered 20/5, 2009 at 14:34 Comment(0)
K
26

That is the way the language used to work. Prior to the using keyword, if you overrode one overloaded function, you had to overload them all:

class bar : public foo 
{
  public:
    bar(void);
    ~bar(void);
    a(int);
    a(double d) { foo::a(d); }  // add this
}

This annoyed enough people that the language committee added the using feature, but some old habits die hard; and the habitués† have a good argument.

As James Hopkins points out, by adding using, the programmer is expressing the intention that the derived class will, without warning, add any future overrides of foo::a() to its list of acceptable signatures.

Here is an example of what he describes:

#include <iostream>
class Base {
public:
  virtual void f(double){ std::cout << "Base::Double!" << std::endl; }
  // virtual void f(int) { std::cout << "Base::Int!" << std::endl; } // (1)
  virtual ~Base() {}
};

class Derived : public Base {
public:
  // using Base::f; // (2)
  void f(double) { std::cout << "Derived::Double!" << std::endl; }
};

int main(int, char **) {
  Derived d;
  d.f(21);
  return 0;
}

The output will be "Derived::Double!" because the compiler will promote the integer argument to a double. g++ 4.0.1 -Wall will not warn that this promotion occurred.

Uncomment (1) to simulate a future change to Base adding the method Base::f(int). The code compiles, again without warning even with -Wall, and "Derived::Double!" remains the output.

Now uncomment (2) to simulate a decision by the Derived programmer to include all Base::f signatures. The code compiles (without warnings), but the output is now "Base::Int!".

† I cannot think of an English word for "those who have the habit" and "addicted" is much too strong.

Kary answered 20/5, 2009 at 14:31 Comment(5)
This is not true at all, you can very well override just one function.Maitland
My only defense is that I wrote a lot of C++ before 1996. Sigh.Kary
@Thomas Habitué is a great word - I've decided to steal it on behalf of the English-speaking world ;-) ('devotee' is the closest I can think of)Geanticline
meriam webster says: Habitué : 1) a person who is often at a specified place or 2) a devoteeAllomorphism
Dogmatist, Conformist, Incorrigible, Obstinate?Rashad
G
14

It is by design. Overload resolution is restricted to a single scope. It prevents some nasty cases of valid code changing meaning when additional functions are added to a base class or to namespace scope.

Geanticline answered 20/5, 2009 at 14:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.