C++ inheritance and name hiding [duplicate]
Asked Answered
O

3

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).

Objectionable answered 5/10, 2015 at 10:29 Comment(4)
This seems like more of a rant than a question. You seem to understand what the behavior of C++ is in this case.Rumpus
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.Carner
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.Heiduc
stroustrup.com/bs_faq2.html#overloadderived explains why it needs to work that way.Hamburg
S
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 ;}
};
Superadd answered 5/10, 2015 at 10:41 Comment(2)
Might want to clarify what you mean by "inner" and "outer" scopes in a class hierarchy.Insolate
Is it work to the case when I have two methodA in Base class?Willson
V
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.

Vibraculum answered 5/10, 2015 at 10:32 Comment(0)
A
0

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/

Abad answered 5/10, 2015 at 10:40 Comment(8)
The hiding rule affects names, so also affects virtual functions.Insolate
@Insolate 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.Anachronism
@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.Insolate
@Insolate 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?Anachronism
@RishitChaudhary - No. I'm describing consequences of the hiding rule.Insolate
@Peter, I think I understood what you are referring to. Is the name hiding you are referring to, similar to this one (referred to as Case 1) in the post): #10173711Anachronism
@RishitChaudhary - Yes, it is the hiding rule that causes "Case 1" to be a diagnosable error.Insolate
@Insolate I understood it now. Thanks for pointing it out.Anachronism

© 2022 - 2024 — McMap. All rights reserved.