2

Suppose I have the following classes:

class Base
{
public:
    virtual void myMethod()
    {

    }

    virtual void myMethod(int x)
    {

    }
};

class Derived : public Base
{
};

In this situation the following code compiles just fine.

int main(void)
{
    Derived obj;
    obj.myMethod();

    return (0);
}

The problem arises when I try to override one of myMethods like below.

class Derived : public Base
{
public:
    virtual void myMethod(int x)
    {

    }
};

Now the code won't compile and gives the error:

error C2660: 'Derived::myMethod' : function does not take 0 arguments

I have overridden one of the overloaded functions and apparently this has hidden the other one from Derived class. To get rid of the error I have to override all the overloads. This is against my expectation and doesn't seem rational to me. Why does this code behave this way?

The problem can be reproduced here.

atoMerz
  • 7,534
  • 16
  • 61
  • 101

3 Answers3

2

Indeed, declaring a function in one scope hides anything with the same name in a wider scope, so your override in the derived class hides the overload in the base class.

This is usually not a problem, since you'd usually interact with polymorphic classes via the base class; and usually what you want, since it prevents changes to the base class from unexpectedly changing the behaviour of code that does interact with the derived class.

But you can easily bring it back into the derived class's scope if you want:

using Base::myMethod;

or refer to the function by qualified name:

obj.Base::myMethod();
Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
1

your compiler is 100% right.
you overloaded your function to take an integer as argument, then this function hid all of the base class function - so obj calls myMethod(int) be default , yet you don't provide your function an integer. if you fix your code to be obj.myMethod(4);

the problem solved.

when overriding a function in the derived class - it hides all the other base class overloads. one can still call the base class with this syntax : obj.Base::myMethod();

In more in depth answer , this is WHY it happens. first of all, we need to understand HOW the compiler compiles Object oriented code. remember - the functions compiles into assembly commands and they sit in the code segment. the variables compiles into rows of memory that sit wither in the stack , heap or data segments. functions sits in on part of the application , the variables in a complete different areas. how does the compiler compile a class with variables AND functions? well, it doesn't. the idea goes like this:

let's say a have a class named X with some variables and some functions
1) take all the member functions and bring them out of the class
2) add another argument to each-now-globally-declared functions - const X* this
3) each time you see the syntax x.someFunc(args..) change it to be someFunc(args..,&x)
4) in the functions - if you don't recognize a symbol - try attaching it a this-> and see if you can compile this
5) compile X as C struct and the other as C functions
6)do the same for derived classes (of course , there is the virtual table issue , but let's stop here)

IN YOUR EXAMPLE:
the psuedo code that might represent the compiler parsed-code is

struct Base{}
struct Derived{}

void myMethod(const Base* this);
void myMethod(int x,const Base* this);
void myMethod(int x, const Derived* this);

//what you tried to do is :
myMethod (&obj);

but the compiler can't find any function that matches these arguments! this is not very intuitive for someone who don't initially knows how object oriented compiles, but it makes more sense after understanding this compiling procedure.

David Haim
  • 25,446
  • 3
  • 44
  • 78
  • Well the question is why would the compiler hide other overloads? I didn't ask for that! I merely override one of the overloads. – atoMerz Apr 18 '15 at 09:32
  • because this is a C++ rule. when you override a function , it hides all other base-class function with the same name. you can still call the base class with obj.Base::myMethod(); – David Haim Apr 18 '15 at 09:33
  • Any references to back that up? – atoMerz Apr 18 '15 at 09:34
  • 1
    Well this is a known fact so I don't have the standard beside me but you can dig this issue , for example, here : http://stackoverflow.com/questions/1628768/why-does-an-overridden-function-in-the-derived-class-hide-other-overloads-of-the – David Haim Apr 18 '15 at 09:36
  • Thanks for the link. This seems counter intuitive but I guess there's no other answer. – atoMerz Apr 18 '15 at 09:42
  • I edited my answer to explain a bit more why does it happen – David Haim Apr 18 '15 at 11:02
  • The 'why' I was looking for was more of a design reasoning 'why', and I think it was mentioned in the link you provided. Hopefully other people will find your technical 'why' more useful. – atoMerz Apr 18 '15 at 15:26
0

By overriding the function in Derived class you hide all overloaded implementations of that function name existing in Base class.

Therefore overriding void Base::myMethod(int) with void Derived::myMethod(int) generates code only for void Derived::myMethod(int) and doesn't for void Derived::myMethod().

As mentioned before you can call Base's function explicitly: obj.Base::myMethod().