Объявление и определение функций

Функции

 

С увеличением объема программы становится невозможным удерживать в па­мяти все детали. Естественным способом борьбы со сложностью любой задачи является ее разбиение на части. В C++ задача может быть разделена на более простые и обозримые с помощью функций, после чего программу можно рассмат­ривать в более укрупненном виде — на уровне взаимодействия функций. Это важно, поскольку человек способен помнить ограниченное количество фактов. Использование функций является первым шагом к повышению степени абстрак­ции программы и ведет к упрощению ее структуры.

 

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

 

 

Функция — это именованная последовательность описаний и операторов, вы­полняющая какое-либо законченное действие. Функция может принимать пара­метры и возвращать значение.

Любая программа на C++ состоит из функций, одна из которых должна иметь имя main (с нее начинается выполнение программы). Функция начинает выпол­няться в момент вызова. Любая функция должна быть объявлена и определена. Как и для других величин, объявлений может быть несколько, а определение только одно. Объявление функции должно находиться в тексте раньше ее вызова для того, чтобы компилятор мог осуществить проверку правильности вызова. Объявление функции (прототип, заголовок, сигнатура) задает ее имя, тип возвра­щаемого значения и список передаваемых параметров. Определение функции со­держит, кроме объявления, тело функции, представляющее собой последова­тельность операторов и описаний в фигурных скобках:

 

[ класс ] тип имя ([ список_параметров ])[throw ( исключения )]

{ тело функции }

 

Рассмотрим составные части определения.

· С помощью необязательного модификатора класс можно явно задать область

видимости функции, используя ключевые слова extern и static:

- extern — глобальная видимость во всех модулях программы (по умлчанию);

- static — видимость только в пределах модуля, в котором определен

· Тип возвращаемого функцией значения может быть любым, кроме массива и функции (но может быть указателем на массив или функцию). Если функция не должна возвращать значение, указывается тип void.

· Список параметров определяет величины, которые требуется передать в функ­цию при ее вызове. Элементы списка параметров разделяются запятыми. Для каждого параметра, передаваемого в функцию, указывается его тип и имя (в объявлении имена можно опускать).

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

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

ными аргументами, а в прототипах имена компилятором игнорируются (они слу­жат только для улучшения читаемости программы).

Функцию можно определить как встроенную с помощью модификатора inline, который рекомендует компилятору вместо обращения к функции помещать ее код непосредственно в каждую точку вызова. Модификатор inline ставится пе­ред типом функции. Он применяется для коротких функции, чтобы снизить на­кладные расходы на вызов (сохранение и восстановление регистров, передача управления). Директива inline носит рекомендательный характер и выполняется компилятором по мере возможности. Использование inline-функций может уве­личить объем исполняемой программы. Определение функции должно предше­ствовать ее вызовам, иначе вместо inline-расширения компилятор сгенерирует обычный вызов. Тип возвращаемого значения и типы параметров совместно определяют тип

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

 

#include <iostream.h>

int sum(int a. int b); // объявление функции

int main(){

int a = 2, b = 3. c, d:

с = sum{a, b); // вызов функции

cin ” d;

cout “ sum(c. d): // вызов функции

return 0;

}

Int sum(int a, int b){ // определение функции

return (a+b);

}

 

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

 

Глобальные переменные

 

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

 

Возвращаемое значение

 

Механизм возврата из функции в вызвавшую ее функцию реализуется опера­тором

return [ выражение ];

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

Примеры:

 

int fl(){return 1;} // правильно

void f2('){return 1:} // неправильно, f2 не должна возвращать значение

double f3(){return 1;} // правильно. 1 преобразуется к типу double

 

Параметры функции

 

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

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

Существует два способа передачи параметров в функцию: по значению и по адресу.

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

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

Если требуется запретить изменение параметра внутри функции, используется модификатор const:

 

int f(const char*):

char* t(char* a, const Int* b):