Пользовательские функции

Функция — это фрагмент кода, который можно неоднократно вызвать из любого места программы. В предыдущих главах мы уже не один раз использовали встроенные функции, входящие в состав стандартной библиотеки. Например, с помощью функции strlen() получали количество символов в C-строке. В этой главе мы рассмотрим создание пользовательских функций, которые позволят уменьшить избыточность программного кода и повысить его структурированность.

Создание функции и ее вызов

Описание функции состоит из двух частей: объявления и определения. Объявление функции (называемое также прототипом функции) содержит информацию о типе. Используя эту информацию, компилятор может найти несоответствие типа и количества параметров. Формат прототипа функции:

<Тип результата> <Название функции>([<Тип> [<Название параметра1>]
                             [, ..., <Тип> [<Название параметраN>]]]);

Параметр <Тип результата> задает тип значения, которое возвращает функция с помощью оператора return. Если функция не возвращает никакого значения, то вместо типа указывается ключевое слово void. Название функции должно быть допустимым идентификатором, к которому предъявляются такие же требования как и к названиям переменных. После названия функции, внутри круглых скобок, указывается тип и название параметров через запятую. Названия параметров в прототипе функции можно не задавать вообще, так как компилятор интересует только тип данных и количество параметров. Если функция не принимает параметров, то указываются только круглые скобки или внутри круглых скобок задается ключевое слово void (в языке C ключевое слово void является обязательным). После объявления функции должна стоять точка с запятой. Пример объявления функций:

int sum(int x, int y);       // или int sum(int, int);
void print(const char *str); // или void print(const char *);
void print_ok();             // или void print_ok(void);

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

<Тип результата> <Название функции>([<Тип> <Название параметра1>
                             [, ..., <Тип> <Название параметраN>]])
{
   <Тело функции>
   [return[ <Возвращаемое значение>];]
}

В отличие от прототипа в определении функции после типа обязательно должно быть указано название параметра, которое является локальной переменной. Эта переменная создается при вызове функции, а после выхода из функции она удаляется. Таким образом, локальная переменная видна только внутри функции. Если название локальной переменной совпадает с названием глобальной переменной, то все операции будут производиться с локальной переменной, а значение глобальной не изменится. Чтобы в этом случае обратиться к глобальной переменной, необходимо перед названием указать оператор ::. Пример:

int sum(int x, int y) {
   int z = x + y; // Обращение к локальной переменной x
   z = ::x + y;   // Обращение к глобальной переменной x
   return z;
}

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

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

int sum(int x, int y) {
   if (x > 0) {
      return x + y;
   }
}

Если переменная x имеет значение больше нуля, то все будет нормально, но если переменная равна нулю или имеет отрицательное значение, то возвращаемое значение не определено и функция вернет произвольное значение, так называемый «мусор». В этом случае при компиляции выводится предупреждающее сообщение: warning: control reaches end of non-void function. Чтобы избежать подобной ситуации, следует в конце тела функции вставить оператор return со значением по умолчанию:

int sum(int x, int y) {
   if (x > 0) {
      return x + y;
   }
   return 0;
}

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

void print_ok() {
   std::cout << "OK" << std::endl;
   return; // Преждевременное завершение функции
   std::cout << "Эта инструкция никогда не будет выполнена!!!";
}

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

print("Message");    // Функция выведет сообщение Message
print_ok();          // Вызываем функцию без параметров
int z = sum(10, 20); // Переменной z будет присвоено значение 30

Переданные значения присваиваются переменным, расположенным в той же позиции в определении функции. Так при использовании функции sum() переменной x будет присвоено значение 10, а переменной y — значение 20. Результат выполнения функции присваивается переменной z.

В качестве примера создадим три разные функции и вызовем их (листинг 12.1).

Листинг 12.1. Создание функций и их вызов

#include <iostream>
#include <clocale>

// Объявления функций
int sum(int x, int y);       // или int sum(int, int);
void print(const char *str); // или void print(const char *);
void print_ok();             // или void print_ok(void);

int main() {
   std::setlocale(LC_ALL, "Russian_Russia.1251");
   // Вызов функций
   print("Сообщение");               // Сообщение
   print_ok();                       // OK
   int z = sum(10, 20);
   std::cout << z << std::endl;      // 30
   return 0;
}

// Определения функций
int sum(int x, int y) {              // Два параметра
   return x + y;
}
void print(const char *str) {        // Один параметр
   std::cout << str << std::endl;
}
void print_ok() {                    // Без параметров
   std::cout << "OK" << std::endl;
}

Учебник C++ (MinGW-W64)
Учебник C++ (MinGW-W64) в формате PDF

Помощь сайту

ЮMoney (Yandex-деньги): 410011140483022

ПАО Сбербанк:
Счет: 40817810855006152256
Реквизиты банка:
Наименование: СЕВЕРО-ЗАПАДНЫЙ БАНК ПАО СБЕРБАНК
Корреспондентский счет: 30101810500000000653
БИК: 044030653
КПП: 784243001
ОКПО: 09171401
ОКОНХ: 96130
Скриншот реквизитов