Значение по умолчанию параметра функции

1.

int Add (int a, int b = 3);
int Add (int a, int b)
{

}

2.

int Add (int a, int b);
int Add (int a, int b = 3)
{

}

Обе работы; какой стандартный способ и почему?

Ответ 1

Если вы поместите объявление в файл заголовка и определение в отдельный файл .cpp и #include заголовок из другого файла .cpp, вы сможете увидеть разницу.

В частности, предположим:

lib.h

int Add(int a, int b);

lib.cpp

int Add(int a, int b = 3) {
   ...
}

test.cpp

#include "lib.h"

int main() {
    Add(4);
}

Компиляция test.cpp не увидит объявление параметра по умолчанию и не сработает с ошибкой.

По этой причине определение параметра по умолчанию обычно указывается в объявлении функции:

lib.h

int Add(int a, int b = 3);

Ответ 2

В С++ требования, предъявляемые к аргументам по умолчанию в отношении их местоположения в списке параметров, следующие:

  • Аргумент по умолчанию для заданного параметра должен быть указан не более одного раза. Указание его более одного раза (даже с тем же значением по умолчанию) является незаконным.

  • Параметры с аргументами по умолчанию должны формировать смежную группу в конце списка параметров.

Теперь, имея в виду, на С++ вам разрешено "вырастить" набор параметров, которые имеют аргументы по умолчанию от одного объявления функции до следующего, при условии, что вышеуказанные требования будут выполняться непрерывно.

Например, вы можете объявить функцию без аргументов по умолчанию

void foo(int a, int b);

Чтобы вызвать эту функцию после такого объявления, вам нужно будет указать оба аргумента явно.

Позже (далее вниз) в той же единице перевода вы можете повторно объявить его снова, но на этот раз с одним аргументом по умолчанию

void foo(int a, int b = 5);

и с этого момента вы можете вызвать его только одним явным аргументом.

Далее вы можете повторно объявить его еще раз, добавив еще один аргумент по умолчанию

void foo(int a = 1, int b);

и с этого момента вы можете вызывать его без явных аргументов.

Полный пример может выглядеть следующим образом

void foo(int a, int b);

int main()
{
  foo(2, 3);

  void foo(int a, int b = 5); // redeclare
  foo(8); // OK, calls `foo(8, 5)`

  void foo(int a = 1, int b); // redeclare again
  foo(); // OK, calls `foo(1, 5)`
}

void foo(int a, int b)
{
  // ...
}

Что касается кода в вашем вопросе, оба варианта совершенно верны, но они означают разные вещи. Первый вариант сразу объявляет аргумент по умолчанию для второго параметра. Второй вариант изначально объявляет вашу функцию без аргументов по умолчанию, а затем добавляет ее для второго параметра.

Чистый эффект обеих ваших объявлений (т.е. способ, которым он воспринимается кодом, который следует за вторым объявлением), точно такой же: функция имеет аргумент по умолчанию для своего второго параметра. Однако, если вам удастся сжать код между первой и второй декларациями, эти два варианта будут вести себя по-другому. Во втором варианте функция не имеет аргументов по умолчанию между объявлениями, поэтому вам нужно будет указать оба аргумента явно.

Ответ 3

Первый способ предпочтительнее второго.

Это связано с тем, что файл заголовка покажет, что параметр является необязательным и каково его значение по умолчанию. Кроме того, это гарантирует, что значение по умолчанию будет одинаковым, независимо от реализации соответствующего .cpp файла.

Во втором случае нет гарантии для значения по умолчанию для второго параметра. Значение по умолчанию может измениться в зависимости от того, как реализован соответствующий .cpp файл.

Ответ 4

Аргументы по умолчанию должны быть указаны с первым вхождением имени функции, как правило, в прототипе функции. Если прототип функции опущен, поскольку определение функции также служит прототипом, тогда аргументы по умолчанию должны быть указаны в заголовке функции.