Почему прототипы функций включают имена параметров, когда они не требуются?
Я всегда думал, что прототип функции должен содержать параметры функции и их имена. Тем не менее, я просто попробовал это:
int add(int,int);
int main()
{
std::cout << add(3,1) << std::endl;
}
int add(int x, int y)
{
return x + y;
}
и это сработало! Я даже пробовал компиляцию с крайней осторожностью:
g++ -W -Wall -Werror -pedantic test.cpp
и он все еще работал. Поэтому мой вопрос: если вам не нужны имена параметров в прототипах функций, почему это так распространено? Есть ли смысл в этом? Имеет ли это какое-то отношение к сигнатуре функции?
6 ответов
нет, они не нужны и фактически игнорируются компилятором. Вы даже можете дать им разные имена в разных декларациях; следующее полностью законно:
int foo(int bar);
int foo(int biz);
int foo(int qux) {
...
}
причина, чтобы поместить их в документации:
- если кто-то читает ваш файл заголовка, они могут сразу сказать, для чего используется каждый параметр.
- если вы используете fancy IDE, он может показать вам имена параметров, когда вы начинаете вводить функцию вызов.
- инструменты документации, такие как Doxygen, могут анализировать имена параметров и показывать их в документации.
имена параметров не являются обязательными и не влияют на компиляцию. Они могут быть размещены там для лучшей читаемости кода.
вам не нужны имена параметров в объявлении. Это чисто документация.
вы даже не нужны имена в определениях:
int f(int)
{
return 0;
}
отлично компилируется на C++ (хотя и не на C). Это иногда полезно, например, для наследования, перегрузки, указателей функций.
вам не нужно включать имена параметров в функции образцов. Вам нужна только полная подпись, которая включает типы параметров и (в случае специализации шаблона функции) возвращаемые значения.
тем не менее, по-прежнему распространено включать имена параметров для записи самодокументирующего кода. То есть функция с этим объявлением:
void foo(int number_of_foos_desired, string foo_replacement);
легче понять, глядя только на прототип, возможно, чем это один:
void foo(int, string);
многие современные IDEs также всплывают имена параметров при вводе при написании кода, который вызывает эту функцию. Возможно, они не смогут открыть эту информацию, если вы не включите имена параметров в прототип.
Он имеет много общего с сигнатурой функции.
одно из преимуществ использования .H файлы - это когда кто-то приходит и хочет понять, что делает ваша программа/api, они могут посмотреть на ваш файл заголовка и получить представление о том, какие операции выполняются, их входы и выходы, как все происходит вместе и т. д.
Если бы вы столкнулись с таким методом, как
int doStuff(int,int)
это было бы намного меньше, чем метод с подписью сказать:
int doStuff(int firstNumberToAdd, int secondNumberToAdd);
со вторым вы, по крайней мере, получите некоторое представление о проводимых операциях и о том, что происходит. Это идея написания самодокументирующего кода.
Если вы заинтересованы, вы можете проверить, Совершенный код Стив Макконнелл.
существуют различные сценарии. Я нашел это очень полезным в работе с inheritance
и virtual functions
. Если вы используете virtual function
который генерирует неиспользуемое предупреждение в подклассе, вы можете опустить имена переменных.