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

Объявление аргумента по умолчанию

Хотя вполне обычной практикой является объявление функции однажды в заголовке, вполне допустимо многократно объявлять ее повторно. Однако у каждого параметра может быть свое значение по умолчанию, определенное только однажды в данной области видимости. Таким образом, любое последующее объявление может добавить значение по умолчанию только для того параметра, у которого ранее не было определено значение по умолчанию. Как обычно, значения по умолчанию могут быть определены, только если у всех параметров справа уже есть значения по умолчанию. Рассмотрим следующий пример:

// у параметров height и width нет значений по умолчанию

string screen(sz, sz, char = ' ');

Нельзя изменить уже заявленное значение по умолчанию:

string screen(sz, sz, char = '*'); // ошибка: переобъявление

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

string screen(sz = 24, sz = 80, char); // ok: добавление аргументов

                                       // по умолчанию

Обычно аргументы по умолчанию определяют при объявлении функции в соответствующем заголовке.

Инициализация аргумента по умолчанию

Локальные переменные не могут использоваться как аргумент по умолчанию. За исключением этого ограничения, аргумент по умолчанию может быть любым выражением, тип которого приводим к типу параметра:

// объявления wd, def и ht должны располагаться вне функции

sz wd = 80;

char def = ' ';

sz ht();

string screen(sz = ht(), sz = wd, char = def);

string window = screen(); // вызов screen(ht(), 80, ' ')

Поиск имен, используемых для аргументов по умолчанию, осуществляется в пределах объявления функции. Значения, представляемые этими именами, вычисляются во время вызова:

void f2() {

 def = '*';   // изменение значения аргумента по умолчанию

 sz wd = 100; // скрывает внешнее определение wd, но не изменяет

              // значение по умолчанию

 window = screen(); // вызов screen(ht(), 80, '*')

}

В функции f2() было изменено значение def. Вызов функции screen передает это измененное значение. Эта функция также объявляет локальную переменную, которая скрывает внешнюю переменную wd. Однако локальное имя wd никак не связано с аргументом по умолчанию, переданным функции screen().

Упражнения раздела 6.5.1

Упражнение 6.40. Какое из следующих объявлений (если оно есть) содержит ошибку? Почему?

(a) int ff(int a, int b = 0, int с = 0);

(b) char *init(int ht = 24, int wd, char bckgrnd);

Упражнение 6.41. Какие из следующих вызовов (если они есть) недопустимы? Почему? Какие из них допустимы (если они есть), но, вероятно, не соответствуют намерениям разработчика? Почему?

char *init(int ht, int wd = 80, char bckgrnd = ' ');

(a) init(); (b) init(24,10); (c) init(14, '*');

Упражнение 6.42. Присвойте второму параметру функции make_plural() (см. раздел 6.3.2) аргумент по умолчанию 's'. Проверьте программу, выведя слова "success" и "failure" в единственном и множественном числе.

<p>6.5.2. Встраиваемые функции и функции <code>constexpr</code></p>

В разделе 6.3.2 приведена небольшая функция, возвращающая ссылку на более короткую строку из двух переданных ей. К преимуществам определения функции для такой маленькой операции относятся следующие.

• Обращение к функции shorterString() проще и понятнее, чем эквивалентное условное выражение.

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

• Если придется внести изменение, проще сделать это в теле функции, а не выискивать в коде программы все случаи применения эквивалентного выражения.

• Функция может быть многократно использована при написании других приложений.

Перейти на страницу:

Похожие книги