Язык программирования C++. Пятое издание - Стенли Липпман
Шрифт:
Интервал:
Закладка:
Оператор goto. Оператор, осуществляющий безусловную передачу управления помеченному оператору в другом месте той же функции. Операторы goto нарушают последовательность выполнения операций программы, поэтому их следует избегать.
Оператор if. Условное выполнение кода на основании значения в условии. Если условие истинно (значение true), тело оператора if выполняется, в противном случае управление переходит к оператору, следующему после него.
Оператор if...else. Условное выполнение кода в разделе if или else, в зависимости от истинности значения условия.
Оператор switch. Оператор условного выполнения, который сначала вычисляет результат выражения, следующего за ключевым словом switch, а затем передает управление разделу case, метка которого совпадает с результатом выражения. Когда соответствующей метки нет, выполнение переходит к разделу default (если он есть) или к оператору, следующему за оператором switch, если раздела default нет.
Оператор throw. Оператор, прерывающий текущий поток выполнения. Каждый оператор throw передает объект, который переводит управление на ближайший раздел catch, способный обработать исключение данного класса.
Оператор while. Оператор цикла, который выполняет оператор тела до тех пор, пока условие остается истинным (значение true). В зависимости от истинности значения условия оператор выполняется любое количество раз.
Оператор выражения (expression statement). Выражение завершается точкой с запятой. Оператор выражения обеспечивает выполнение действий в выражении.
Передача (raise, throwing). Выражение, которое прерывает текущий поток выполнения. Каждый оператор throw передает объект, переводящий управление на ближайший раздел catch, способный обработать исключение данного класса.
Помеченный оператор (labeled statement). Оператор, которому предшествует метка. Метка (label) — это идентификатор, сопровождаемый двоеточием. Метки используются независимо от других одноименных идентификаторов.
Потерянный оператор else (dangling else). Разговорный термин, используемый для описания проблемы, когда во вложенной конструкции операторов if больше, чем операторов else. В языке С++ оператор else всегда принадлежит ближайшему расположенному выше оператору if. Чтобы указать явно, какому из операторов if принадлежит конкретный оператор else, применяются фигурные скобки.
Пустой оператор (null statement). Пустой оператор представляет собой отдельный символ точки с запятой.
Составной оператор (compound statement). Синоним блока.
Управление потоком (flow of control). Управление последовательностью выполнения операций в программе.
Устойчивость к исключениям (exception safe). Термин, описывающий программы, которые ведут себя правильно при передаче исключения.
Функция terminate(). Библиотечная функция, вызываемая в случае, если исключение так и не было обработано. Обычно завершает выполнение программы.
Глава 6
Функции
В этой главе описано, как объявлять и определять функции. Здесь также обсуждается передача функции аргументов и возвращение из них полученных значений. В языке С++ функции могут быть перегружены, т.е. то же имя может быть использовано для нескольких разных функций. Мы рассмотрим и то, как перегрузить функции, и то, как компилятор выбирает из нескольких перегруженных функций ее соответствующую версию для конкретного вызова. Завершается глава описанием указателей на функции.
Функция (function) — это именованный блок кода. Запуск этого кода на выполнение осуществляется при вызове функции. Функция может получать любое количество аргументов и (обычно) возвращает результат. Функция может быть перегружена, следовательно, то же имя может относиться к нескольким разным функциям.
6.1. Основы функций
Определение функции (function definition) обычно состоит из типа возвращаемого значения (return type), имени, списка параметров (parameter) и тела функции. Параметры определяются в разделяемом запятыми списке, заключенном в круглые скобки. Выполняемые функцией действия определяются в блоке операторов (см. раздел 5.1), называемом телом функции (function body).
Для запуска кода функции используется оператор вызова (call operator), представляющий собой пару круглых скобок. Оператор вызова получает выражение, являющееся функцией или указателем на функцию. В круглых скобках располагается разделяемый запятыми список аргументов (argument). Аргументы используются для инициализации параметров функции. Тип вызываемого выражения — это тип возвращаемого значения функции.
Создание функцииВ качестве примера напишем функцию вычисления факториала заданного числа. Факториал числа n является произведением чисел от 1 до n. Факториал 5, например, равен 120:
1 * 2 * 3 * 4 * 5 = 120
Эту функцию можно определить следующим образом:
// факториал val равен
// val * (val - 1) * (val - 2) ... * ((val - (val - 1)) * 1)
int fact(int val) {
int ret = 1; // локальная переменная для содержания результата по
// мере его вычисления
while (val > 1)
ret *= val--; // присвоение ret произведения ret * val
// и декремент val
return ret; // возвратить результат
}
Функции присвоено имя fact. Она получает один параметр типа int и возвращает значение типа int. В цикле while вычисляется факториал с использованием постфиксного оператора декремента (см. раздел 4.5), уменьшающего значение переменной val на 1 при каждой итерации. Оператор return выполняется в конце функции fact и возвращает значение переменной ret.
Вызов функцииЧтобы вызвать функцию fact(), следует предоставить ей значение типа int. Результатом вызова также будет значение типа int:
int main() {
int j = fact(5); // j равно 120, т.е. результату fact(5)
cout << "5! is " << j << endl;
return 0;
}
Вызов функции осуществляет два действия: он инициализирует параметры функции соответствующими аргументами и передает управление коду этой функции. При этом выполнение вызывающей (calling) функции приостанавливается и начинается выполнение вызываемой (called) функции.
Выполнение функции начинается с неявного определения и инициализации ее параметров. Таким образом, когда происходит вызов функции fact(), сначала создается переменная типа int по имени val. Эта переменная инициализируется аргументом, предоставленным при вызове функции fact(), которым в данном случае является 5.
Выполнение функции заканчивается оператором return. Как и вызов функции, оператор return осуществляет два действия: возвращает значение (если оно есть) и передает управление назад вызывающей функции. Возвращенное функцией значение используется для инициализации результата вызывающего выражения. Выполнение продолжается с остальной частью выражения, в составе которого осуществлялся вызов. Таким образом, вызов функции fact() эквивалентен следующему:
int val = 5; // инициализировать val из литерала 5
int ret = 1; // код из тела функции fact
while (val > 1)
ret *= val--;
int j = ret; // инициализировать j копией ret
Параметры и аргументыАргументы — это инициализаторы для параметров функции. Первый аргумент инициализирует первый параметр, второй аргумент инициализирует второй параметр и т.д. Хотя порядок инициализации параметров аргументами известен, порядок обработки аргументов не гарантирован (см. раздел 4.1.3). Компилятор может вычислять аргументы в любом порядке по своему предпочтению.
Тип каждого аргумента должен совпадать с типом соответствующего параметра, как и тип любого инициализатора должен совпадать с типом объекта, который он инициализирует. Следует передать точно такое же количество аргументов, сколько у функции параметров. Поскольку каждый вызов гарантированно передаст столько аргументов, сколько у функции параметров, последние всегда будут инициализированы.
Поскольку у функции fact() один параметр типа int, при каждом ее вызове следует предоставить один аргумент, который может быть преобразован в тип int (см. раздел 4.11):