В C или C++, каково различие между объявлением функции и функциональной подписью?
Я знаю что-то вроде объявления функции, но функциональная подпись полностью плохо мне знакома. Какой смысл того, чтобы иметь понятие функциональной подписи? Для чего используются эти два понятия на самом деле?
Спасибо!
Объявление функции - это прототип для функции (или он может исходить из определения функции, если компилятор не видел прототипа в этот момент) - он включает тип возврата, имя функции и типы параметров (опционально в C).
Сигнатура функции - это часть объявления функции, которую компилятор использует для разрешения перегрузки. Поскольку несколько функций могут иметь одно и то же имя (т.е. они перегружены), компилятору нужен способ определить, к какой из нескольких возможных функций с определенным именем должен разрешиться вызов функции. Сигнатура - это то, что компилятор учитывает при разрешении перегрузки. В частности, стандарт определяет "сигнатуру" как:
информацию о функции, которая участвует в разрешении перегрузки: типы ее параметров и, если функция является членом класса, cv-квалификаторы (если таковые имеются) самой функции и класса, в котором объявлена функция-член.
Обратите внимание, что тип возврата не является частью сигнатуры функции. Как сказано в сноске к стандарту, "сигнатуры функций не включают тип возврата, поскольку он не участвует в разрешении перегрузки".
Сигнатура функции не включает тип возвращаемого значения или тип связи функции.
Хорошо, Википедия не согласна со мной по поводу включения типа возвращаемого значения. Однако я знаю, что тип возвращаемого значения не используется компилятором при принятии решения о том, соответствует ли вызов функции сигнатуре. Этот предыдущий вопрос StackOverflow, похоже, согласуется: Является ли тип возвращаемого значения частью сигнатуры функции?
Объявление функции - это прототип. Подпись функции указывает тип возвращаемого значения и используемые параметры, составляющие подпись. Рассмотрим это:
int foo(int, int); /* Function Declaration */ /* Implementation of foo ** Function signature */ int foo(int a, int b){ }
Теперь рассмотрим следующий сценарий: программиста спрашивают, какова сигнатура функции для foo
:
int
int
, названный a
и b
соответственно Прототип функции, с другой стороны, указывает компилятору C / C ++, что нужно ожидайте, и если подпись не соответствует прототипу, компилятор выдаст ошибку в контексте «ошибки объявления функции» или «несоответствия прототипа».
Стандарт определяет два термина: декларация и определение. Определение - это предварительное заявление. Однако стандарты C99 и C ++ 03 имеют немного разные определения.
Из черновика C ++ 0x:
Приложение C
8.3.5 Изменение: в C ++ функция, объявленная с пустым списком параметров, не принимает аргументов . . В C пустой список параметров означает, что количество и тип аргументов функции неизвестны »
Определения
1.3.11 подпись
имя и параметр - type-list (8.3.5) функции, а также класс , концепция, карта концепций или пространство имен , членом которого она является. Если {{ 1}} функция или шаблон функции является членом класса, его подпись дополнительно включает квалификаторы cv (если есть) и квалификатор ссылки ( если есть) в самой функции или шаблоне функции. Подпись ограниченного члена (9.2) включает в себя требования к его шаблону . Подпись { Шаблон функции {1}} дополнительно включает тип возвращаемого значения, список параметров шаблона и требования к шаблону (если есть). Подпись специализация шаблона функции включает подпись шаблона , специализацией которого она является, и его аргументы шаблона (независимо от того, указаны ли явно или де duced). [ Примечание: подписи используются в качестве основы для изменения имен и связывания. — Конец примечание]
Также обратите внимание, что const верхнего уровня и volatile на аргументе не являются частью сигнатуры, согласно стандарту. Но некоторые компиляторы понимают это неправильно.
Например,
void f(const int, const char* const);
имеет ту же сигнатуру, что и
void f(int, const char*);