Member function hidden in derived class
Please look at the following code:
#include <iostream>
using namespace std;
class A {
public:
A() {};
virtual void foo(double d) { cout << d << endl; }
virtual void foo(double d, int a) = 0;
};
class B : public A {
public:
B() {};开发者_JS百科
virtual void foo(double d, int a) { cout << d << endl << a << endl; }
};
int main()
{
B b;
b.foo(3.14);
return 0;
}
The compiler (tried g++ and visual c++ 2008) says that there's no function like B:foo(double). The exact message of g++ is:
main.cpp:21: error: no matching function for call to ‘B::foo(double)’
It looks like the effect of hiding rule, but in my opinion the rule should not be used here, since I'm not overriding foo(double) and both foo methods are defined in base class.
I know that I can fix the problem with
using A::foo;
declaration in the derived class B.
Can you explain why the code does not compile and what rules of C++ apply here?
The hiding rule is not about overriding, it is about hiding of names. If the derived class declares a member function, this hides other base class member functions with the same name. This also happens in your case.
Names shadow, not specific functions. Once you make a foo
in B
, all base foo
's (note, by name!) are shadowed.
When the compiler encounters an identifier, the lookup rules kick in and start searching for that identifier. In your concrete situation, with b.foo
, the compiler knows that foo
must be a member of B
or one of its subclasses. The lookup rules state that the compiler must start with the most derived class (considering the static type of the object) and follow up in the hierarchy, and that once the identifier is found in one level only definitions in that level will be considered, it must not keep looking upwards.
B& f(); // might return a B or something derived from B
void test() {
B& b = f(); // static type is B
b.foo(1.0);
}
Regardless of what f
returns, the static type is B
, so the compiler will lookup in B
class and find B::foo(double,int)
. Since there is no other foo
declaration at that level, the compiler must try to match (and fail) the function call with the available method declarations.
The important thing is that the lookup does not look the object but rather looks by type and going upwards, cutting as soon as it encounters the first instance.
Looks perfectly reasonable to me. Although function signature does matter to know what the function is, I can see how this behavior prevents very stupid mistakes.
As ereOn suggested, using directive would be a fair price to pay.
精彩评论