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