Ответ 1
Очень приятный вопрос, сложный случай поиска имени.
В принципе, когда имя f
просматривается в области C
, оно всегда находит A::f
из-за использования-объявления. Итак, все вызовы c.f()
, c.C::f()
и f()
в C::test()
, разрешите имя f
на A::f
.
Далее идет виртуальная отправка. Если виртуальная функция вызывается неквалифицированным именем, происходит динамическая отправка и вызывается окончательный переадресация. Это охватывает c.f()
и вызов f()
в C::test()
, так как они являются неквалифицированными.
В вызове c.C::f()
используется квалифицированное имя для f
, которое подавляет динамическую отправку и функцию, для которой вызываемое имя вызывается напрямую. Поскольку эта функция A::f
(благодаря использованию-декларации), A::f
называется не виртуальным. Соответствующие правила следуют (цитируя С++ 14 окончательный проект N4140, акцент мой):
§10.3/15
Явная квалификация с оператором области (5.1) подавляет механизм виртуального вызова.
§5.2.2/1
... Если выбранная функция не виртуальна, или если id-выражение в выражении доступа к члену класса является квалифицированным id,, который вызывается этой функцией. В противном случае его конечный переопределитель (10.3) в динамическом типе выражения объекта; такой вызов называется вызов виртуальной функции.