Почему прототипы функций включают имена параметров, когда они не требуются?

Я всегда думал, что прототип функции должен содержать параметры функции и их имена. Тем не менее, я просто попробовал это:

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 который генерирует неиспользуемое предупреждение в подклассе, вы можете опустить имена переменных.