if (expected != actual)

 error_msg({"functionX", expected, actual});

else

 error_msg({"functionX", "okay"});

Здесь той же функции error_msg() передаются при первом вызове три значения, а при втором — два.

У функции с параметром initializer_list могут быть также и другие параметры. Например, у нашей системы отладки мог бы быть класс ErrCode, представляющий различные виды ошибок. Мы можем пересмотреть свою программу так, чтобы в дополнение к списку initializer_list передавать параметр типа ErrCode следующим образом:

void error_msg(ErrCode е, initializer_list il) {

 cout << e.msg() << ": ";

 for (const auto &elem : il)

  cout << elem << " ";

 cout << endl;

}

Поскольку класс initializer_list имеет члены begin() и end(), мы можем использовать для обработки элементов серийный оператор for (см. раздел 5.4.3). Эта программа, как и предыдущая версия, перебирает элементы заключенного в фигурные скобки списка значений, переданных параметру il.

Для этой версии необходимо пересмотреть вызовы так, чтобы передать аргумент типа ErrCode:

if (expected != actual)

 error_msg(ErrCode(42), {"functionX", expected, actual});

else

 error_msg(ErrCode(0), {"functionX", "okay"});

Параметр в виде многоточия

Параметры в виде многоточия предоставляются языком С++ для взаимодействия программам с кодом на языке С, использующим такое средство библиотеки С, как varargs. В других целях параметр в виде многоточия не следует использовать. Использование varargs описано в документации компилятора С.

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

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

void foo(parm_list, ...);

void foo(...);

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

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

Упражнение 6.27. Напишите функцию, получающую параметр типа initializer_list и возвращающую сумму элементов списка.

Упражнение 6.28. Во второй версии функции error_msg(), где у нее есть параметр типа ErrCode, каков тип элемента в цикле for?

Упражнение 6.29. При использовании типа initializer_list в серийном операторе for использовали бы вы ссылку как управляющую переменную цикла? Объясните почему.

<p>6.3. Типы возвращаемого значения и оператор <code>return</code></p>

Оператор return завершает выполнение функции и возвращает управление той функции, которая вызвала текущую. Существуют две формы оператора return:

return;

return выражение;

<p><image l:href="#reader.png"/>6.3.1. Функции без возвращаемого значения</p>

Оператор return без значения применим только в такой функции, типом возвращаемого значения которой объявлен void. Функции, возвращаемым типом которых объявлен void, необязательно должны содержать оператор return. В функции типа void оператор return неявно размещается после последнего оператора.

Как правило, функции типа void используют оператор return для преждевременного завершения выполнения. Это аналогично использованию оператора break (см. раздел 5.5.1) для выход из цикла. Например, можно написать функцию swap(), которая не делает ничего, если значения идентичны:

void swap(int &v1, int &v2) {

 // если значения равны, их замена не нужна; можно выйти сразу

 if (v1 == v2)

  return;

 // если мы здесь, придется поработать

 int tmp = v2;

 v2 = v1;

 v1 = tmp;

 // явно указывать оператор return не обязательно

}

Сначала эта функция проверяет, не равны ли значения, и если это так, то завершает работу. Если значения не равны, функция меняет их местами. После последнего оператора присвоения осуществляется неявный выход из функции.

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

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