Поиск имени - это отдельная фаза для разрешения перегрузки .
Поиск имени происходит первым.Это процесс определения того, к какой области относится имя.В этом случае мы должны решить, означает ли d.foo
d.D::foo
, или d.B1::foo
, или d.B2::foo
.Правила поиска имени не принимают во внимание параметры функции или что-либо еще;речь идет исключительно об именах и областях.
Только после того, как это решение принято, мы затем выполняем разрешение перегрузки для различных перегрузок функции в области, в которой было найдено имя.
В вашем примере вызов d.foo()
нашел бы D::foo()
, если бы была такая функция.Но нет ни одного.Таким образом, работая в обратном направлении, он пробует базовые классы.Теперь foo
может равным образом выглядеть до B1::foo
или B2::foo
, так что это неоднозначно.
По той же причине вы получите двусмысленность, вызывая неквалифицированную foo(5);
внутри D
функции-члена.
Эффект рекомендуемого решения:
struct Derived : public Base1, public Base2{
using Base1::foo;
using Base2::foo;
состоит в том, что это создает имя D::foo
и идентифицирует две функции.В результате d.foo
преобразуется в d.D::foo
, и затем разрешение перегрузки может произойти для этих двух функций, которые обозначены D::foo
.
Примечание. В этом примере D::foo(int)
и Base1::foo(int)
два идентификатора для одной функции;но в целом для поиска имен и разрешения перегрузки не имеет значения, являются ли они двумя отдельными функциями или нет.