2

Given the following...

#include <iostream>
using namespace std;

class BaseClass {
public:
    void Func(float f) {
        cout << "BaseClass:Func() called!";
    }
};

class SubClass : public BaseClass {
};

int main() {
    SubClass sub;
    sub.Func(1.1f);
    return 0;
}

This runs pretty much as one would expect, resulting in the following output...

BaseClass:Func() called!

However, if I add the following function to SubClass...

class SubClass : public BaseClass {
public:
    void Func(int i) {                        // accepts an int, not a float!
        cout << "SubClass::Func() called!";
    }
};

Like any other overload, I would expect the SubClass function to be called if I supply an int as my argument, and BaseClass's if I supply a float. However, if I run the program as-is (ie. with the float), this is not the case...

SubClass::Func() called!

Instead of what I was expecting, the float I provided is cast to an integer, and the SubClass function is called. It seems SubClass's function effectively shadows BaseClass's function, even though its signature differs.

Can someone shed some light on this? Is there a way to call the BaseClass function via a SubClass instance without having to cast it?

Thanks!

Syndog
  • 1,531
  • 4
  • 19
  • 27

2 Answers2

5

As you said, the BaseClass's function is hidden by the SubClass's. The name Func will be found at the SubClass's scope, then name lookup stops, Func in BaseClass won't be considered at all, even it's more appropriate. They're not "overloads" at all.

See Unqualified name lookup.

You can use using to introduce them into the same scope to make overloading works.

class SubClass : public BaseClass {
public:
    using BaseClass::Func;
    ~~~~~~~~~~~~~~~~~~~~~
    void Func(int i) {                        // accepts an int, not a float!
        cout << "SubClass::Func() called!";
    }
};
songyuanyao
  • 169,198
  • 16
  • 310
  • 405
  • Strange use of a word with a well-defined meaning, that is a 'scope'. In a given form, the answer is misleading. – SergeyA Mar 08 '16 at 14:36
  • @SergeyA Would you please explain more about what do you mean "it has nothing to do with scope"? `Func` is found at the derived class scope, the name in base class scope won't be considered for overloading, isn't it? – songyuanyao Mar 08 '16 at 14:43
  • Scope has very specific meaning. When you say 'won't cross different scopes' it is not clear what you mean by those different scopes - are you saying that you won't cross from block scope to class level scope? Or something else? In fact, this statement has no meaning. What you should've said is that the base function is hidden and thus invisible, rather then overloaded. And do not bring scope here. – SergeyA Mar 08 '16 at 14:53
2

The subclass' Func method will hide the base class' Func method in the member name lookup, and will thus be called with any numeric argument, casted to an integer.

If you want to use both methods in the subclass, pull the base class' Func method by using using BaseClass::Func;. This will treat the base Func as being a member of the subclass, no longer being hidden by the subclass' name lookup.

owacoder
  • 4,815
  • 20
  • 47