In C++, the order of name lookup is governed by name resolution rules that take into account scopes, hiding, and the specifics of inheritance. Key points:
Resolving conflicts:
class Base { public: void foo(int) {} }; class Derived : public Base { public: using Base::foo; void foo(double) {} // Overloaded version };
Base::x or Base::foo().Example of ambiguity in diamond inheritance:
struct A { int x; }; struct B : virtual A {}; struct C : virtual A {}; struct D : B, C { void test() { x = 42; } // OK: x is unique, thanks to virtual };
If there is a method foo(int) declared in the base class, and foo(double) in the derived class, is foo(int) accessible from an object of the derived class?
Answer: No, the method foo(double) "hides" all overloaded versions of foo from the base class. To access foo(int), you need to explicitly write using Base::foo or call Base::foo.
Example:
class Base { public: void foo(int) { } }; class Derived : public Base { public: void foo(double) {} }; Derived d; d.foo(3); // Error! foo(int) is not visible
We use:
class Derived : public Base { public: using Base::foo; void foo(double) {} }; d.foo(3); // Everything works
Story
In a project with multiple inheritance, a class was inherited from two bases with the same foo() methods. The authors did not use virtual inheritance, leading to two copies of the base class being created — all calls to foo() became ambiguous, and the compiler refused to compile the code. This was resolved by using virtual inheritance and explicitly stating Base::foo() on the call.
Story
In a graphics engine, one derived class defined its own draw(), not using using for the base class draw(). When the code was refactored, the wrong version of draw() was called — parts of the interface stopped rendering. The error was only found after a deep examination of the class structure.
Story
When moving to a new compiler, compilation became impossible due to name ambiguities in multiple and virtual inheritance. The previously working implementation did not account for different include chains, leading to different sets of names in the translation unit.