Почему С++ позволяет нам окружать имя переменной в круглых скобках при объявлении переменной?
Например, объявление, например:
int (x) = 0;
Или даже это:
int (((x))) = 0;
Я наткнулся на это, потому что в моем коде у меня был фрагмент, похожий на следующий:
struct B
{
};
struct C
{
C (B *) {}
void f () {};
};
int main()
{
B *y;
C (y);
}
Очевидно, я хотел построить объект C
, который затем сделал бы что-то полезное в своем деструкторе. Однако, как это бывает, компилятор рассматривает C (y);
как объявление переменной y
с типом C
и, следовательно, печатает ошибку о переопределении y
. Интересно, что если я напишу его как C (y).f ()
или как-то вроде C (static_cast<B*> (y))
, он будет компилироваться по назначению. Лучшее современное решение - использовать {}
в вызове конструктора, конечно.
Итак, после того, как я понял, возможно объявить переменные типа int (x) = 0;
или даже int (((x))) = 0;
, но я никогда не видел, чтобы кто-то действительно использовал объявления вроде этого. Поэтому мне интересно - какова цель такой возможности, потому что на данный момент я вижу, что она только создает случай, похожий на пресловутый "самый неприятный синтаксический разбор" и не добавляет ничего полезного?
Ответы
Ответ 1
Группировка.
В качестве конкретного примера рассмотрим, что вы можете объявить переменную типа функции, например
int f(int);
Теперь, как бы вы указали указатель на такую вещь?
int *f(int);
Нет, не работает! Это интерпретируется как функция, возвращающая int*
. Вам нужно добавить в круглые скобки, чтобы он правильно разобрал:
int (*f)(int);
То же самое касается массивов:
int *x[5]; // array of five int*
int (*x)[5]; // pointer to array of five int
Ответ 2
В таких объявлениях обычно разрешено использовать круглые скобки, потому что декларация с синтаксической точки зрения всегда выглядит так:
<front type> <specification>;
Например, в следующем объявлении:
int* p[2];
"Тип фронта" int
(не int*
), а "спецификация" - * p[2]
.
Правило состоит в том, что вы можете использовать любое количество круглых скобок по мере необходимости в части "спецификация", потому что иногда они неизбежно устраняют неоднозначность. Например:
int* p[2]; // array of 2 pointers to int; same as int (*p[2]);
int (*p)[2]; // pointer to an array of 2 ints
Указатель на массив является редким случаем, однако в той же ситуации у вас есть указатель на функцию:
int (*func(int)); // declares a function returning int*
int (*func)(int); // declares a pointer to function returning int
Это прямой ответ на ваш вопрос. Если ваш вопрос касается утверждения типа C(y)
, то:
- Поместите круглые скобки вокруг всего выражения -
(C(y))
, и вы получите то, что захотите.
- Этот оператор ничего не делает, кроме создания временного объекта, который перестает жить после окончания этой инструкции (я надеюсь, что это именно то, что вы намеревались сделать).