Программирование на C и C++

Онлайн справочник программиста на C и C++

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

Язык С++ позволяет присваивать параметрам функции значения по умолчанию в том случае, когда при вызове функции не указываются параметры. Значения по умолчанию задаются синтаксически сходным образом с инициализацией переменных. Например, ниже объявляется функция f(), имею­щая аргументом целую переменную, значением которой по умолчанию является величина 1:

void f (int i = 1)
{
...
}

Теперь функция f() может вызываться двумя способами, как показано ниже:

f(10); // явная передача значения
f (); // функция использует значение по умолчанию

В первом случае аргументу i будет присвоено значение 10. Во втором случае i получит значение по умолчанию, равное 1.

Аргументы по умолчанию в языке С++ позволяют программисту писать более простой код. Для того, чтобы охватывать множество ситуаций, часто функция содержит больше параметров, чем это необходимо при ее наиболее типичном использовании. Используя аргументы по умолча­нию, можно указать только аргументы, которые отличаются от значений по умолчанию в каж­дой конкретной ситуации.

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

// выводит строку в позиции X, Y
void xyout (char *str, int x = 0, int у = 0)
{
if (!x) x = wherex ();
if (!y) у = wherey();
gotoxy(x, y);
cout << str;
}

Эта функция выводит на экран строку, на которую указывает переменная str, причем эта строка размещается на экране в координатах х и у. Однако, если ни одна из координат х или у не указа­на, то строка выводится в то место экрана, которое соответствует текущим значениям у. (Можно представить себе эту функцию как усовершенствованную версию функции puts()). Функции wherex(), wherey() и gotoxy() являются библиотечными функциями Borland С++. Функции wherex() и wherey() возвращают текущие значения координат х и у. Эти текущие координаты определяют, куда будут выводиться данные. Функция gotoxy() перемещает курсор в точку с заданными координатами х и у.

Следующая короткая программа демонстрирует использование функции xyout().

#include <iostream.h>
#include <conio.h>
void xyout(char *str, int x = 0, int у = 0)
{
if (!x) x = wherex ();
if (!y) у = wherey();
gotoxy(x, y);
cout << str;
}
int main()
{
xyout("hello", 10, 10);
xyout(" there");
xyout("l like С+ + ", 40); // по-прежнему на десятой строке
xyout("This is on line 11.\n", 1, 11);
xyout("This follows on line 12.\n");
xyout("This follows on line 13.");
return 0;
}

Посмотрите внимательно на вызов функции xyout() в функции main(). Эта программа выводит на экран данные, как показано ниже. Как показывает эта программа, хотя иногда бывает полезно указать, куда именно на экран выводить данные, часто можно просто продолжать вывод с той точки, где окончился вывод предыдущей порции данных. Использование аргументов по умолчанию позволяет применять одну и ту же функцию в обоих случаях, так что нет необходи­мости в двух отдельных функциях.

Пример вывода функции xyout()
                  hello there                I like С++
This is on line 11.
This follows on line 12.
This follows on line 13.

Обратим внимание, что функции main() и xyout() вызываются с тремя, двумя или одним аргу­ментом. В случае вызова с одним аргументом величины х и у задаются по умолчанию. При вызове с двумя аргументами величина у задается по умолчанию. Однако невозможно вызвать функцию xyout() с величиной х, заданной по умолчанию, и величиной у, заданной при вызове функции. В общем случае при вызове функции ее аргументы совмещаются с соответствующими параметрами слева направо. После того, как всем использованным при вызове функции аргументам поставле­ны в соответствие параметры, оставшимся аргументам присваиваются их значения по умолчанию.

При создании функции, имеющей аргументы по умолчанию, их значения должны быть указа­ны только один раз, причем в тот самый момент, когда функция первый раз объявляется в файле. Например, если функция xyout() определена после функции main(), то аргументы по умолчанию
должны объявляться в прототипе функции xyout(), но эти значения больше не должны повто­ряться при определении функции xyout(). Следующая программа иллюстрирует сказанное:

#include <iostream.h>
#include <conio.h>
void xyout(char *str, int x = 0, int у = 0)
int main()
{
xyout("hello", 10, 10);
xyout(" there");
xyout("l like С++", 40); // по-прежнему на десятой строке
xyout("This is on line 11.\n", 1, 11);
xyout("This follows on line 12. \n");
xyout("This follows on line 13.");
return 0;
}
/* Поскольку значения по умолчанию для х и у уже определены в прототипе xyout(), то они не могут быть повторены здесь */
void xyout (char *str, int x, int y)
{
if (!x) x = wherex();
if (!y) у = wherey();
gotoxy(x, y);
cout << str;
}

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

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

При определении параметров важно понимать, что все параметры по умолчанию располага­ются правее параметров, которые не имеют значений по умолчанию. Это означает, что после того, как определен параметр, имеющий значение по умолчанию, нельзя ввести в интерфейсе функции параметр, не имеющий значения по умолчанию. Например, следующее объявление фун­кции xyout() является некорректным:

// некорректно!
void xyout (int х = 0, int у = 0, char *str)

Ниже показана еще одна некорректная попытка использования параметра по умолчанию:

// некорректно!
int f(int i, int j = 10, int k)

После того как начались параметры по умолчанию, в списке не могут появиться параметры, не имеющие значения по умолчанию.

Также можно использовать параметры со значениями по умолчанию в конструкторе объекта. В качестве примера ниже приведена новая версия конструктора класса queue:

/* Конструктор, использующий значение по умолчанию */
queue::queue(int id=0)
{
sloc = rloc = 0;
who = id;
cout << "Queue " << who << " initialized. \n";
}

В этой версии при объявлении объекта без инициализации каким-либо значением параметр id принимает значение по умолчанию, равное 0. Например, в результате объявления

queue a, b(2);

создаются два объекта — а и b. Значение id для объекта а равно 0, а для объекта b равно 2.