Категории
Самые читаемые
Лучшие книги » Компьютеры и Интернет » Программирование » Язык программирования C++. Пятое издание - Стенли Липпман

Язык программирования C++. Пятое издание - Стенли Липпман

Читать онлайн Язык программирования C++. Пятое издание - Стенли Липпман

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 72 73 74 75 76 77 78 79 80 ... 297
Перейти на страницу:

С учетом предыдущей командной строки argc содержит значение 5, a argv — следующие символьные строки в стиле С:

argv[0] = "prog"; // может также указывать на пустую строку

argv[1] = "-d";

argv[2] = "-o";

argv[3] = "ofile";

argv[4] = "data0";

argv[5] = 0;

При использовании аргументов в массиве argv помните, что дополнительные аргументы начинаются с элемента argv[1]; элемент argv[0] содержит имя программы, а не введенный пользователем параметр.

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

Упражнение 6.25. Напишите функцию main(), получающую два аргумента. Конкатенируйте предоставленные аргументы и выведите полученную строку.

Упражнение 6.26. Напишите программу, которая способна получать параметры командной строки, описанные в этом разделе. Отобразите значения аргументов, переданных функции main().

6.2.6. Функции с переменным количеством параметров

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

Новый стандарт предоставляет два основных способа создания функций, получающих переменное количество аргументов: если у всех аргументов тот же тип, можно передать объект библиотечного класса initializer_list. Если типы аргументов разные, можно написать функцию специального вида, известную как шаблон с переменным количеством аргументов (variadic template), который мы рассмотрим в разделе 16.4.

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

Параметры типа initializer_list

Функцию, получающую произвольное количество аргументов одинакового типа, можно написать, используя параметр типа initializer_list. Тип initializer_list — это библиотечный класс, который представляет собой массив (см. раздел 3.5) значений определенного типа. Этот тип определен в заголовке initializer_list. Операции, предоставляемые классом initializer_list, перечислены в табл. 6.1.

Таблица 6.1. Операции, предоставляемые классом initializer_list

initializer_list<T> lst; Инициализация по умолчанию; пустой список элементов типа T initializer_list<T> lst{a,b,с...}; lst имеет столько элементов, сколько инициализаторов; элементы являются копиями соответствующих инициализаторов. Элементы списка — константы  lst2(lst) lst2 = lst Копирование или присвоение объекта класса. initializer_list не копирует элементы в списке. После копирования первоисточник и копия совместно используют элементы lst.size() Количество элементов в списке lst.begin() lst.end() Возвращает указатель на первый и следующий после последнего элементы lst 

Подобно типу vector, тип initializer_list является шаблоном (см. раздел 3.3). При определении объекта класса initializer_list следует указать тип элементов, которые будет содержать список:

initializer_list<string> ls; // initializer_list строк

initializer_list<int> li;    // initializer_list целых чисел

В отличие от вектора, элементы списка initializer_list всегда константы; нет никакого способа изменить значение его элементов.

Функцию отображения сообщений об ошибках с переменным количеством аргументов можно написать следующим образом:

void error_msg(initializer_list<string> il) {

 for (auto beg = il.begin(); beg != il.end(); ++beg)

  cout << *beg << " ";

 cout << endl;

}

Методы begin() и end() объектов класса initializer_list аналогичны таковым у класса vector (см. раздел 3.4.1). Метод begin() предоставляет указатель на первый элемент списка, а метод end() — на следующий элемент после последнего. Наша функция инициализирует переменную beg указателем на первый элемент и перебирает все элементы списка initializer_list. В теле цикла осуществляется обращение к значению beg, что позволяет получить доступ к текущему элементу и вывести его значение.

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

// expected и actual - строки

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<string> 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<int> и возвращающую сумму элементов списка.

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

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

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

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

return;

return выражение;

6.3.1. Функции без возвращаемого значения

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

1 ... 72 73 74 75 76 77 78 79 80 ... 297
Перейти на страницу:
На этой странице вы можете бесплатно скачать Язык программирования C++. Пятое издание - Стенли Липпман торрент бесплатно.
Комментарии