6

I know this is not the first question on this subject, but all the other related questions (and answers) I read were slightly out of the point, according to me. Take the code

#include <iostream>

using namespace std ;

class Base {
public:
    void methodA() { cout << "Base.methodA()" << endl ;}
};

class Derived : public Base {
public:
    void methodA(int i) { cout << "Derived.methodA(int i)" << endl ;}
};

int  main()
{
  Derived obj;
  obj.methodA();
}

Compiling this code with a recent version of g++ gives the error

no matching function for call to 'Derived::methodA()'

It is because of this error that I came upon Stackoverflow to find an answer. But none of the answers was convincing to me. The signatures of the two methods present no ambiguity in distinguishing them, the compiler should be able to pick up the method in the base class. Just comment out

class Derived : public Base {
//public:
//    void methodA(int i) { cout << "Derived.methodA(int i)" << endl ;}
};

and the code works as expected. This means that it is just the member function name to hide the same name member function in the base class, and the signature is not taken into consideration, like if function names were not mangled (mangling should resolve any ambiguity in this case). Some else wrote in a similar question that this is against the spirit of C++ (and Object Orientation, I add) and I perfectly agree with him. This is a limitation of function overloading for which I really do not see any sound reason.

Apparently the question has been closed, so I am not able to add a reply, after reading the answers, other than by editing my own initial question. I am fairly sure (but I am not in the position to prove it) that in older C++ compilers the code in my initial question would compile (and then execute) with no problem. My point is that I really do not see the rationale behind that language design (as it has been called in the replies) choice. The compiler, in this case, has available all the information in order to take the proper action, and this is what I would expect. Otherwise it looks like, by language design choice, it has been chosen not to take into consideration the signature of the member functions, which sounds quite weird. I read the article at "programmerinterview" indicated just above, but it does not explain what motivated that language design choice (furthermore, the "someFunction" in the "GrandChildClass" in the example code by the end of that article, does not override, as stated, the same name ascendant class member function: the two same name member functions have different signatures - so it is not an overriding).

4
  • 2
    This seems like more of a rant than a question. You seem to understand what the behavior of C++ is in this case. Commented Oct 5, 2015 at 10:33
  • other way, someone else may say this is an advantage of function overloading... it is what the language defines at the end of the day that holds good. Commented Oct 5, 2015 at 10:44
  • Voted re-open. If somebody has one of the old books they could find the quotes involved about it. For the record, I think both the rejected bad behavior and the current spec are both slightly off. I suppose it's possible he once had a compiler that did what I wish the standard did, that is match on number of arguments passed. Commented Oct 5, 2015 at 16:49
  • stroustrup.com/bs_faq2.html#overloadderived explains why it needs to work that way. Commented Oct 23, 2017 at 8:56

3 Answers 3

10

That is the way the language is designed - names in inner scopes hide names in outer scopes. Here the derived class acts as an inner scope and the base class as an outer scope.

The fact that the functions would be considered overloads if they were in the same scope, doesn't matter. The hiding works on the names, not on individual functions.

You can override the default, by explicitly adding the name to the derived class:

class Derived : public Base {
public:
    using Base::methodA;   // Now it is visible!

    void methodA(int i) { cout << "Derived.methodA(int i)" << endl ;}
};
Sign up to request clarification or add additional context in comments.

2 Comments

Might want to clarify what you mean by "inner" and "outer" scopes in a class hierarchy.
Is it work to the case when I have two methodA in Base class?
2

This means that it is just the member function name to hide the same name member function in the base class, and the signature is not taken into consideration

Correct. That is the way the language was designed. I don't really like that language design feature either. But it is well documented and you don't have a choice.

Comments

1

I think you already understood. Its called Name Hiding and this is how the language is made. But i don't see it as an inconvenience as you get pretty comfortable with these convention eventually when you spend time with C++. When you define a non virtual method with the same name as Base method it hides the Base class method in Derived class so you are getting the error for

obj.methodA();

To avoid hiding of Base class methods in Derived class, you can do :

obj.Base::methodA();

For more info: http://www.programmerinterview.com/index.php/c-cplusplus/c-name-hiding/

8 Comments

The hiding rule affects names, so also affects virtual functions.
@Peter the hiding rule does not affect virtual functions as the call is resolved at run time using a virtual table of the class, that contains pointers to the most derived definitions of the virtual functions called. In case of virtual function call resolution, the entire function signature (names and parameter(s)) is taken into account, not just the function name.
@RishitChaudhary - You have misinterpreted my point. In the example given in this question, if Base::methodA() is made virtual, it is still hidden by Derived::methodA(int). And that would be true if Derived::MethodA(int) was virtual.
@Peter are you saying that using <Name_of_class>::<Name_of_function>() overrides the behavior for virtual functions and resolved the function calls at compile-time itself?
@RishitChaudhary - Yes, it is the hiding rule that causes "Case 1" to be a diagnosable error.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.