Вызов метода и типа метода С++ неоднозначность
Я надеюсь, что название фактически описывает то, что я хотел спросить...
Я написал фрагмент кода, который компилируется с помощью gcc и работает так, как я предполагал. Однако он не компилируется с llvm, и код выполняется по-разному при компиляции с icc!
Вот пример проблемы:
#include <iostream>
using std::cout; using std::endl;
class A {
public:
virtual void foo() { cout << "A::foo()" << endl; }
};
class B : public A {
public:
typedef A base;
virtual void foo() { cout << "B::foo()" << endl; }
};
int main() {
typedef B base;
base* bp = new B();
bp->base::foo();
}
Выход gcc: A:: foo()
icc output: B:: foo()
Может кто-нибудь объяснить, что говорит стандарт об этом случае?
Ответы
Ответ 1
Из С++ 11, §3.4.5/4:
Если id-выражение в доступе к члену класса является квалифицированным идентификатором
форма
class-name-or-namespace-name::...
имя класса или имени пространства имен
после. или → оператор сначала просматривается в классе
выражение объекта и имя, если найдено, используется. В противном случае это
искал в контексте всего постфиксного выражения.
Я не думаю, что это может быть яснее. Это находит B::base
, поэтому вывод
должен быть A::foo()
.
Ответ 2
Я думаю, что эта часть стандарта имеет значение:
3.4.3.1 Члены класса [class.qual]
1) Если спецификатор вложенного имени квалифицированного идентификатора назначает класс, имя, указанное после Вложенные имена в именах классов (10.2), за исключением случаев, перечисленных ниже. Название должно представлять одно или больше членов этого класса или одного из его базовых классов (п. 10). [Примечание. Член класса может ссылаться на использование идентификатора с квалификацией указывают на его потенциальный охват (3.3.7). -end note] Исключения из правилом поиска имени является следующее:
- имя деструктора посмотрел вверх, как указано в 3.4.3;
- идентификатор типа конверсии Идентификатор функции преобразования просматривается таким же образом, как и идентификатор типа преобразования в доступе к члену класса (см. 3.4.5);
- имена в шаблоне-аргументе идентификатора шаблона просматриваются в контексте в котором происходит все постфиксное выражение.
- поиск имени указанная в использовании-декларации (7.3.3), также находит класс или имена перечислений, скрытые в той же области (3.3.10).
base::
в этом случае, как представляется, "назначает" класс, поэтому поиск выполняется в рамках класса. Я не вижу, как может применяться любой из случаев исключения, поэтому он является областью действия класса, так как base
эквивалентен A
.
(5.1.1-8 указывает, что в этом случае он является квалифицированным идентификатором и применяется 3.4.3.1)