Просто, чтобы было ясно, что происходит. Посмотрите на этот пример
int main() {
float a = 0;
{
int(a); // no-op?
a = 1;
}
cout << a;
}
Что выйдет? Ну, он выведет 0
.int(a)
из выше, может быть обработан двумя различными способами:
- Cast к Int и отбрасывать результат
- Объявляет переменную с именем
a
. Но игнорируйте круглые скобки вокруг идентификатора.
Компилятор, когда возникает такая ситуация, когда в выражении используется выражение в стиле функции, и оно также выглядит как объявление, оно всегда воспринимается как объявление. Когда он не может синтаксически быть объявлением (компилятор будет рассматривать всю строку, чтобы определить это), он будет считаться выражением. Таким образом, мы присваиваем внутреннему a
выше, оставляя внешний a
равным нулю.
Теперь ваше дело именно это. Вы пытаетесь (случайно) объявить идентификатор, называемый A
в классе под названием X
:
X (X::A); // parsed as X X::A;
Компилятор затем переходит к стонать о не объявлялись конструктор по умолчанию, так как статические, так как она предполагает, что это будет, по умолчанию построено. Но даже если у вас был конструктор по умолчанию для X, он, конечно, по-прежнему ошибочен, потому что ни A
не является статическим членом X, ни статикой X не может быть определена/объявлена в области блока.
Вы можете сделать это не выглядеть как заявление, делая несколько вещей. Во-первых, вы можете разбить все выражение, что делает его больше не похожим на объявление. Или просто отмените тип, на который наложено. Оба этих disambiguations были упомянуты в других ответах:
(X(X::A)); (X)(X::A)
Существует аналогичная, но отчетливая неоднозначность при попытке фактически объявить объект. Посмотрите на этот пример:
int main() {
float a = 0;
int b(int(a)); // object or function?
}
Поскольку int(a)
может быть как декларация параметра называется a
и явное преобразование (литая) флоат-переменной к междунар, компилятор снова решает, что это заявление. Таким образом, мы объявляем функцию с именем b
, которая принимает целочисленный аргумент и возвращает целое число. Существует несколько возможностей устранить это, исходя из значений, указанных выше:
int b((int(a))); int b((int)a);
Скобки, конечно, решают проблему, но я не уверен, как это можно рассматривать как объявление функции, учитывая, что X :: A не является типом. Синтаксически это может быть тип, но тогда X x (X :: A) будет столь же неоднозначным. – Ari
Мое чтение сообщения об ошибке состоит в том, что компилятор считает, что анонимный объект является копией. Вот почему это говорит о «X X :: A», а не о «X :: A». Но я не могу понять, почему он так думает. – Ari
Ari: Я фактически запутался в сообщении об ошибке, потому что это то же самое, когда вы опускаете все круглые скобки, и это явно (для компилятора) объявление переменной (A типа X, внутри области X). Но это * должно * рассматриваться как объявление функции компилятором в соответствии со стандартом. –