TITLE: Name hiding or everything I didn't want to know about scopes PROBLEM: drm@cats.com (Derek R. Marsano) Here's a strange behavior from the Sun C++ 2.1 compiler. Class A defines two virtual functions which overload the name 'foo'. Class B, derived from A, overrides one of these virtual functions. The compiler complains that B::foo() hides BOTH of the A::foo() implementations (not just the foo(int) implementation we intend to override). RESPONSE: jamshid@ut-emx.uucp (Jamshid Afshar), 25 Oct 91 Strange but correct. You have encountered the C++ name-hiding rules: a member function in a derived class will hide *all* functions of the same name in the base class, *not* overload them, even if they're virtual. So, if you override or overload one foo() in a derived class, you must redefine in class Derived all the Base::foo()'s that you wish to access from a Derived object. The fact that the functions are virtual isn't really relevant to any of this (though it is usually where the problem is noticed), so as a simplified example (from the ARM 13.1): struct B { int f(int); }; struct D : public B { int f(char*); // hides all member funcs in B named `f' }; D d; d.f(1); // error: only f(char*) is visible You must define an `int f(int)' in D's definition to use it: struct D : public B { int f(int i) { return B::f(i); } int f(char*); }; Here's the text from ARM section 13.1, pp 310 (Declaration Matching): Two function declarations of the same name refer to the same function if they are in the same scope and have identical argument types. A function member of a derived class is *not* in the same scope as a function member of the same name in a base class. As for why this was done, it was decided that the amount of trouble that would have been caused by confusion like the following is greater than the amount of effort it takes to redefine overloaded functions in a derived class. // base.h: hidden in some dark corner of your disk drive class Base { public: void foo(int); }; // derived.h: most users only read this header, not base.h #include class Derived : public Base { public: void foo(double); }; // client.cc #include ... Derived d; d.foo(1); // Without name-hiding, this would call Base::foo(int). // Client: "Why isn't foo(double) being called?! It's // the only foo() I see in class Derived!" Whether name-hiding is a good thing or not is debatable, but I believe it is. Also, I imagine this decision was made from bad experiences with the "intuitive" way. One thing I'm not sure of is whether "access declarations" can be used to get around completely redefining the functions. ARM 11.3, Access Declarations, p247, says "The access to a base class member cannot be adjusted in a derived class that also defines a member of that name." class X { public: void f(int); }; class Y : public X { public: X::f; // should this make f(int) accessible? void f(char*); }; void bar() { Y y; y.f(5); // BC++ error: type mismatch in param 1 } Since X::f(int) is public, and Y is derived from `public X', I don't think `X::f;' is "adjusting access". Is BC++ wrong or am I? [...]