Как уже отмечали другие, линия
void func();
внутри main
рассматривается как прототип функции, а не как вызов функции func
. В C и C ++ вы можете объявить прототипы функций внутри функций, если хотите, хотя на практике это редко делается.
Тот факт, что это законно, вызывает у программистов всевозможные головные боли. Например, если вы переписали код как
(void) func();
Тогда это будет скомпилировано как вызов func
, тип возвращаемого значения которого явно приведен к void
, чтобы указать: «Меня не волнует это возвращаемое значение». Другими словами, этот набор скобок превращает объявление в оператор.
В C ++ эта проблема может усугубляться тем фактом, что приведенный ниже код является прототипом функции, а не объявлением переменной, вызывающим конструктор по умолчанию:
Object myObject();
Хотя
Object myObject(137);
создает объект и передает 137 в его конструктор, а
Object myObject;
создает объект без вызова конструктора.
Существует ужасный крайний случай языка, называемого "самым неприятным синтаксическим анализом", который возникает при попытке объявить объект при вызове его конструктора. Например, этот код является допустимым C ++, но это объявление функции, а не объявление переменной:
set<int> mySet(istream_iterator<int>(cin), istream_iterator<int>());
Проблема в том, что это может быть проанализировано как объявление функции, а не как создание объекта, который принимает два временных istream_iterator<int>
s в качестве параметров. Чтобы это исправить, в C ++ вам нужно написать
set<int> mySet(istream_iterator<int>(cin), (istream_iterator<int>()));
Где, как и выше, лишние скобки принудительно устраняют неоднозначность оператора от прототипа функции до объявления.
Надеюсь, это поможет!