Проблема, с которой вы столкнулись, связана с тем, как работает поиск имен в C ++. В частности, при разрешении члена компилятор проверяет статический тип объекта, к которому осуществляется доступ к члену. Если идентификатор найден в этом классе, то поиск завершается и (в случае функций-членов) начинается разрешение перегрузки. Если идентификатор не найден, он будет сканировать иерархию, класс за классом, пытаясь найти идентификатор по одному уровню за раз .
В вашем конкретном случае у вас есть c->onFoo();
и c
типа C
. Компилятор не видит никакого объявления onFoo
в C
, поэтому он продолжает вверх в иерархии. Когда компилятор проверяет B
, он видит, что на этом уровне есть объявление void onFoo(int i)
, поэтому он останавливает поиск и пытается разрешить перегрузку. В настоящее время разрешение перегрузки не выполняется из-за несогласованности аргументов.
Тот факт, что объявление void onFoo(int)
присутствует на уровне B
, имеет эффект , скрывающий остальные перегрузки в любом базовом классе, так как он остановит поиск. Обратите внимание, что это проблема с неквалифицированным поиском, функция все еще там и применима к объекту, но не будет найдена при обычном поиске (вы все равно можете назвать ее как c->A::onFoo()
).
Что касается того, что делать с скрытием , то самый простой способ - использовать объявление using для переноса функций в область действия:
class B : A {
public:
using A::onFoo; // All A::onFoo overloads are *considered* here
void onFoo( int );
};
Эффект объявления using
здесь заключается в том, что при поиске класса B
в поиске идентификатора onFoo
компилятор также учитывает все перегрузки onFoo
в базовом классе. , включив обычный поиск, можно найти A::onFoo()
.