The issue that you are experiencing is related to how name lookup works in C++. In particular, when resolving a member, the compiler will look into the static type of the object on which the member is being accessed. If the identifier is found in that class, then lookup completes and (in the case of member functions) overload resolution starts. If the identifier is not found, it will crawl up the hierarchy, class by class, trying to locate the identifier one level at a time.
In your particular case, you have c->onFoo();
and c
is of type C
. The compiler does not see any declaration of onFoo
in C
, so it continues upwards in the hierarchy. When the compiler checks B
, it sees that there is a declaration of void onFoo(int i)
at that level, so it stops lookup, and tries overload resolution. At this time, the overload resolution fails due to the inconsistency in the arguments.
The fact that a declaration of void onFoo(int)
is present at B
level has the effect of hiding the rest of the overloads in any base class, as it will stop lookup. Note that this is a problem with unqualified lookup, the function is still there and applicable to the object, but will not be found by regular lookup (you can still call it as c->A::onFoo()
).
As of how to deal with hiding, the simplest way is by employing the using declaration to bring the functions into scope:
class B : A {
public:
using A::onFoo; // All A::onFoo overloads are *considered* here
void onFoo( int );
};
The effect of the using
declaration here is that when the B
class is looked up, in search for the onFoo
identifier, the compiler is instructed to also consider all overloads of onFoo
in the base class, enabling regular lookup to find A::onFoo()
.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…