ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 23.06.2021

Просмотров: 1699

Скачиваний: 3

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
background image

51 

11. Функции в Си++ 

 
С увеличением объема программы становится невозможно удерживать в памяти 

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

Часто используемые функции можно помещать в библиотеки. Таким образом, 

создаются более простые в отладке и сопровождении программы. 

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

Функция – это именованная последовательность описаний и операторов, 

выполняющая законченное  действие, например, формирование массива, печать 
массива и т. д. 

Функция, во-первых, является одним из производных типов СИ++, а ,во-вторых, 

минимальным исполняемым модулем программы. 

 
 
 
 
 
 
Любая функция должна быть объявлена и определена. 
Объявление функции (прототип, заголовок) задает имя функции, тип 

возвращаемого значения и список передаваемых параметров.  

Определение функции содержит, кроме объявления, тело функции, которое 

представляет собой последовательность описаний и операторов. 

тип имя_функции([список_формальных_параметров]) 
{ тело_функции} 
 
Тело_функции – это блок или составной оператор. Внутри функции нельзя 

определить другую функцию. 

В теле функции должен быть оператор, который возвращает полученное 

значение функции в точку вызова. Он может иметь 2 формы: 

1)

return выражение; 

2)

return; 

Первая форма используется для возврата результата, поэтому выражение 

должно иметь тот же тип, что и тип функции в определении. Вторая форма 
используется, если функция не возвращает значения, т. е. имеет тип void. Программист 
может не использовать этот оператор в теле функции явно, компилятор добавит его 
автоматически в конец функции перед }.  

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

может быть указателем на массив или функцию.  

Список формальных параметров – это те величины, которые требуется передать 

в функцию. Элементы списка разделяются запятыми. Для каждого параметра 
указывается тип и имя. В объявлении имена можно не указывать. 

Для того, чтобы выполнялись операторы, записанные в теле функции, функцию 

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

Функция 

Исх. данные (параметры, 
передаваемые в функцию) 

Результат (возвращаемое 

 значение) 


background image

52 

Фактические параметры заменяют формальные параметры при выполнении операторов 
тела функции. Фактические и формальные параметры должны совпадать по количеству 
и типу.  

 
Объявление функции должно находиться в тексте раньше вызова функции, 

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

Пример: 
Заданы координаты сторон треугольника. Если такой треугольник существует, 

то найти его площадь. 

1. Математическая модель: 

1)

l=sqrt(pow(x1-x2,2)+pow(y1-y2,2));//длина стороны треугольника 

2)

p=(a+b+c)/2; 

s=sqrt(p*(p-a)*(p-b)*(p-c));//формула Герона 

3)

проверка существования треугольника 

(a+b>c&&a+c>b&&c+b>a) 

2. Алгоритм: 

1)

Ввести координаты сторон треугольника (х1,у1),(х2,у2),(х3,у3); 

2)

Вычислить длины сторон ab, bc, ca; 

3)

Проверить существует ли треугольник с такими сторонами. Если да, то 

вычислить площадь и  вывести результат. 

4)

Если нет, то вывести сообщение. 

5)

Если все координаты равны 0, то конец, иначе возврат на п.1. 

 
#include <iostream.h> 
#include <math.h> 
 
double line(double x1,double y1,double x2,double y2) 

//функция возвращает длину отрезка, заданного координатами x1,y1 и x2,y2 
return sqrt(pow(x1-x2,2)+pow(y1-y2,2)); 

double square(double a, double b, double c) 

//функция возвращает площадь треугольника, заданного длинами сторон а,b,c 
double s, p=(a+b+c)/2; 
return s=sqrt(p*(p-a)*(p-b)*(p-c));//формула Герона 

bool  triangle(double a, double b, double c) 

//возвращает true, если треугольник существует 
if(a+b>c&&a+c>b&&c+b>a) return true; 
else return false; 

void main() 

double x1=1,y1,x2,y2,x3,y3;  
double point1_2,point1_3,point2_3; 
do 


background image

53 


cout<<"\nEnter koordinats of triangle:"; 
cin>>x1>>y1>>x2>>y2>>x3>>y3; 
point1_2=line(x1,y1,x2,y2); 
point1_3=line(x1,y1,x3,y3); 
point2_3=line(x2,y2,x3,y3); 
if(triangle(point1_2,point1_3,point2_3)==true) 
cout<<"S="<<square(point1_2,point2_3,point1_3)<<"\n"; 
else cout<<"\nTriagle doesnt exist"; 

while(!(x1==0&&y1==0&&x2==0&&y2==0&&x3==0&&y3==0)); 

11.2.Прототип функции 

Для того, чтобы к функции можно было обратиться, в том же файле должно 

находиться определение или описание функции (прототип).  

double line(double x1,double y1,double x2,double y2); 
double square(double a, double b, double c); 
bool  triangle(double a, double b, double c); 
double line(double ,double ,double ,double); 
double square(double , double , double ); 
bool  triangle(double , double , double ); 
Это прототипы функций, описанных выше. 
При наличии прототипов вызываемые функции не обязаны размещаться в одном 

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

Имя_файла – определяет заголовочный файл, содержащий прототипы группы 

стандартных для данного компилятора функций. Например, почти во всех программах 
мы использовали команду #include <iostream.h> для описания объектов потокового 
ввода-вывода и соответствующие им операции.  

При разработке своих программ, состоящих из большого количества функций, и 

, размещенных в разных модулях, прототипы функций и описания внешних объектов 
(констант, переменных, массивов) помещают в отдельный файл, который включают в 
начало каждого из модулей программы с помощью директивы include”имя_файла”. 

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

Основным способом обмена информацией между вызываемой и вызывающей 

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

При передаче по значению выполняются следующие действия: 
-

вычисляются значения выражений, стоящие на месте фактических 

параметров; 

-

в стеке выделяется память  под формальные параметры функции; 

-

каждому фактическому параметру присваивается значение формального 

параметра, при этом проверяются соответствия типов и при необходимости 
выполняются их преобразования. 


background image

54 

Пример: 
double square(double a, double b, double c) 

//функция возвращает площадь треугольника, заданного длинами сторон а,b,c 
double s, p=(a+b+c)/2; 
return s=sqrt(p*(p-a)*(p-b)*(p-c));//формула Герона 

1) double s1=square(2.5,2,1); 
2) double a=2.5,b=2,c=1; 
double s2=square(a,b,c); 
3) double x1=1,y1=1,x2=3,y2=2,x3=3,y3=1; 
double s3=square(sqrt(pow(x1-x2,2)+pow(y1-y2,2)),//расстояние между 1и2 
 sqrt(pow(x1-x3,2)+pow(y1-y3,2)), //расстояние между 1 и 3 
sqrt(pow(x3-x2,2)+pow(y3-y2,2)));//расстояние между 2 и3 
 
Стек 
A  2

.5 

B  2 
C  1 
S   
P   
P и S – локальные переменные. 
Т. о. в стек заносятся копии фактических параметров и операторы функции 

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

 При передаче по адресу в стек заносятся копии адресов параметров, 

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

Пример. 
void Change(int a,int b)//передача по значению 
{int r=a;a=b;b=r;} 
 
int x=1,y=5; 
Change(x,y); 
A  1 

B  5 

cout<<”x=”<<x<<”y=”<<y; 
выведется: x=1y=5 
void Change(int *a,int *b)//передача по адресу 
{int r=*a;*a=*b;*b=r;} 
int x=1,y=5; 
Change(&x,&y); 
A  &

B  &

cout<<”x=”<<x<<”y=”<<y; 


background image

55 

выведется: x=5y=1 
Для передачи по адресу также могут использоваться ссылки. При передаче по 

ссылке в функцию передается адрес указанного при вызове параметра, а внутри 
функции все обращения к параметру неявно разыменовываются. 

void Change(int &a,int &b) 
{int r=a;a=b;b=r;} 
int x=1,y=5; 
Change(x,y); 
A  &

B  &

cout<<”x=”<<x<<”y=”<<y; 
выведется: x=5y=1 
Использование ссылок вместо указателей улучшает читаемость программы, т. к. 

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

11.4. Локальные и глобальные переменные 

Переменные, которые используются внутри данной функции, называются 

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

int*f() 

int a;   
. . . .  
return&a;// НЕВЕРНО 

Глобальные переменные – это переменные, описанные вне функций. Они видны 

во всех функциях, где нет локальных переменных с такими именами. 

Пример: 
int a,b;//глобальные переменные 
void change() 

int r;//локальная переменная 
r=a;a=b;b=r; 

void main() 

cin>>a,b; 
change(); 
cout<<”a=”<<a<<”b=”<<b;