В C++ порядок поиска имён регулируется правилами разрешения имён (name lookup), которые учитывают области видимости (scope), скрытие (hiding) и специфику наследования. Ключевые моменты:
Разрешение конфликтов:
class Base { public: void foo(int) {} }; class Derived : public Base { public: using Base::foo; void foo(double) {} // Перегруженная версия };
Base::x или Base::foo().Пример неоднозначности при diamond inheritance:
struct A { int x; }; struct B : virtual A {}; struct C : virtual A {}; struct D : B, C { void test() { x = 42; } // OK: x один, благодаря virtual };
Если в базовом классе объявлен метод foo(int), а в производном — foo(double), доступен ли foo(int) из объекта производного класса?
Ответ: Нет, метод foo(double) "скрывает" все перегруженные версии foo из базового класса. Для доступа к foo(int) нужно явно написать using Base::foo или Base::foo в вызове.
Пример:
class Base { public: void foo(int) { } }; class Derived : public Base { public: void foo(double) {} }; Derived d; d.foo(3); // Ошибка! foo(int) не виден
Используем:
class Derived : public Base { public: using Base::foo; void foo(double) {} }; d.foo(3); // Всё работает
История
В проекте с множественным наследованием появился класс, унаследованный от двух базовых с одинаковыми методами foo(). Авторы не использовали virtual inheritance, создавалось две копии базового класса — все обращения к foo() становились неоднозначными, компилятор отказывался собирать код. Решилось применением virtual inheritance и явным указанием Base::foo() при вызове.
История
В графическом движке один дочерний класс определял свой draw(), не делая using для draw() базового класса. При перевороте кода (Refactor) вызывалась не та версия draw() — части интерфейса перестали отрисовываться. Ошибка нашлась только после глубокого разбора структуры классов.
История
При переезде на новый компилятор компиляция стала невозможной из-за неоднозначности имен при множественном и виртуальном наследовании. Ранее работавшая реализация не учитывала разные цепочки include, приводящие к разным наборам имён в единице трансляции.