What's the rationale behind the hiding rule in C++?
class A { void f(int); }
class B : public A { void f(double); } // B::f(int) is hidden
If it is a meaningful feature I think it should also be possible to hide functions without defining new functions with the same name: something like this:
class B : public A { hide void f(double); }
but this is not possible.
I don't think it simplifies compilers job, since compilers must anyway be able to unhide functions when you explicitly use the
using
directive:class B : public A { using A::f; void f(double); } // B::f(int) NOT hidden
So, how come there is a hiding rule?
Hum, all the three answers seem to be good, and show different rationales for the hiding rule. I'm not sure about which answer I should accept.
Probably, the reason is template specialization. I give you an example:
The template class B has a method
f()
, but until you don't create an instance of the class B you don't know the signature. So the callthis->f()
is anytime "legal". Both GCC and CLang don't report error until you create the instance. But when you call the methodg()
on aB<1>
instance they indicate the error. So the hiding rule keep simpler to check if your code is valid.I report the last part of code used in my example.
Another reason for hiding base class's member function (with same name but different signatures) might be due to ambiguity caused by optional parameters. Consider the following example:
If the
foo
method in base class hadn't become hidden, it wouldn't be possible for compiler to decide whetherA::foo
should be called orB::foo
since the following line matches both signatures:It's an hairy question, but apparently the idea is that this hiding feature helps avoiding subtle bugs when making changes to a base class (that could otherwise "steal" calls that before would have been handled by the derived class). Still a change in a base class can influence the result of compilation of derived classes so I don't think I understand 100% this explanation.
I agree that this topic is so frequently discussed that probably the hiding actually increases the amount of "surprises" in C++ programmers.
A detailed discussion about this issue can be found here...
i don't know the original rationale, but since hide or not hide are about equally bad choices wrt. to functions, i'm guessing the rationale is to have uniform rules: the same as for names defined in nested curly-braces scopes.
the hiding helps you in some ways.
adding a method to a base class will by default not affect overload resolution for a derived class.
and you do not run afoul of overload resolution by some mishap directing your call with say argument
false
, to a base class method with formal argumentvoid*
. such things.cheers & hth.,
I'm sure I've seen this case offered by a C++ bigwig, not sure which:
Now, add
void f(int);
toBase
, and the meaning of main changes - it callsBase::f
becauseint
is a better match forchar
- it's an integer promotion rather than a standard conversion.It's not clear whether that change to the base would really be intended by the programmer to catch calls with
char
, so requiringusing
to be explicit means the default behavior is that the change doesn't affect the calling code. I believe it's a marginal call, but I think the committee decided that base classes in C++ were fragile enough as they are, without this too :-)There's no need for a "hide" keyword because there's no comparable case for hiding "f" from the Base when it isn't overloaded in Derived.
Btw, I've chosen the types, and
char
is deliberately incongruous. You can get more subtle cases withint
vsunsigned int
rather thanint
vschar
.