Эта декларация:
typedef int foo();
вполне допустимо. Он определяет foo
как псевдоним для типа int()
, или «функция возвращает int
и не принимает никаких аргументов».
(В сторону: C использует (void)
не указывают на отсутствие аргументов, C++ использует ()
Более ранняя версия этого ответа было основано на правилах C.).
Это чаще для определения определений типов для типов указатель на функцию а не для типов функций, но оба действительны. Учитывая вышеизложенное ЬурейеЕ, вы можете объявить функцию указатель на объект как:
foo *funcptr;
Но вы не можете объявить или определить функцию с помощью ЬурейеЕ. Если язык допускает это, вы могли бы объявить функцию:
foo func; /* would be equivalent to "int func(void);" *if* it were legal */
или:
foo func { return 42; }; /* would be equivalent to
"int func(void) { return 42; }"
*if* it were legal */
Есть еще раз, когда это будет удобно. Стандартная signal
функция, определенная в <signal.h>
или <csignal>
, имеет довольно сложную декларацию:
void (*signal(int sig, void (*func)(int)))(int);
Вы можете определить typedef
для типа функции обработчика сигнала:
typedef void (signal_handler)(int);
бы позволила бы signal
к быть объявлен как:
void (*signal(int sig, signal_handler *func);
, но вы не можете себе это определение типа, чтобы объявить или определить свой собственный обработчик сигнала - хотя вы можете с пользой использовать его, чтобы объявить указатели сигнализировать функции обработчика:
signal_handler *funcptr = my_handler;
signal(SIGINT, funcptr);
То же самое относится и к аргументам указателя функции, требуемые qsort()
и bsearch()
.
Так что, учитывая, что вы можете определить typedef для типа функции, почему вы не можете использовать его для объявления или определения функции?
Я не думаю, что есть какая-то серьезная причина. Язык просто не позволяет этого. Для объявления функций, одна проблема заключается в том, что
signal_handler foo;
выглядит точно так же, как в объявлении объекта, но вместо этого объявить функцию (которая должна быть определена в другом месте). И разрешение определений типов для функции определения:
signal_handler foo { /* ... */ }
потребует изменения грамматики языка - и было бы трудно увидеть параметры и возвращаемые типы при взгляде на определение. Кроме того, определения функций, в отличие от объявлений, требуют имен для любых параметров, что добавит еще один уровень сложности.
Но я считаю, что настоящая причина в том, что Деннис Ритчи, когда он проектировал С, либо не думал об этом, либо не думал, что это стоит (и у Страуструпа не было достаточной причины для измените это, когда он разработал C++).
Типы функций не являются объектами. Вы не можете «объявить переменную типа функции». Вы можете только «объявить функцию». Вот как это язык. –