9

I have this code:

#include <iostream>
#include <string>

using namespace std;

class A {
    public: void Print(int i) {cout<<i;}
};

class B : public A {
    public: void Print(string s) {cout<<s;}
};

int main() {
    B bInstance;
    bInstance.Print(1);
    return 0;
}

This gives me an error:

error: invalid conversion from 'int' to 'const char*' [-fpermissive]

meaning it is trying to call B's Print without considering the inherited overload. But, A's Print should be callable by a B instance. In fact, if I change the call to

bInstance.A::Print(1);

then it compiles without any errors, but I wanted to avoid having to write the class scope operator each time. Is there a way to tell the compiler I am trying to call the base class's overload of the function?

Peter Wood
  • 22,682
  • 5
  • 57
  • 94
Mic
  • 339
  • 2
  • 7
  • 2
    Overload resolution is done before searching `A` because it found something in `B`. Use a `using` statement to bring `A`'s in and have it participate in overload resolution. – chris Mar 21 '13 at 19:40
  • If I may humbly suggest that the usefulness of overloading is sometimes somewhat overrated. Consider using distinct names instead, such as `void printInt( int i );` and `void printString( string s );` – bobobobo Mar 21 '13 at 19:42

1 Answers1

13

The Print() member function in your subclass hides the member function Print() of the superclass. Therefore, the compiler will not see A::Print() and will try to invoke B::Print(), complaining that an int could not be converted into a string.

To bring A::Print() into the overload set, you can introduce a using declaration:

class A {
public: 
    void Print(int i) {cout<<i;}
};

class B : public A {
public:
    using A::Print;
//  ^^^^^^^^^^^^^^^
    void Print(string s) {cout<<s;}
};

Here is a live example of your code working after the necessary modifications.

Andy Prowl
  • 119,862
  • 22
  • 374
  • 446