Определение, описание и вызовы функций 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Определение, описание и вызовы функций



Функции

Определение, описание и вызовы функций

Программа на языке С++ представляет собой совокупность произвольного количества функций, одна (и единственная) из которых - главная функция с именем main. Выполнение программы начинается и заканчивается выполнением функции main. Выполнение неглавных функций инициируется в главной функции непосредственно или в других функциях, которые сами инициируются в главной.

Функции – это относительно самостоятельные фрагменты программы, оформленные особым образом и снабженные именем.

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

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

По умолчанию все функции внешние (класс памяти extern), доступны во всех файлах программы. При определении функции допускается класс памяти static, если надо чтобы функция использовалась только в данном файле программы.

 

Определение функции

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

Определение состоит из заголовка и тела функции:

 

<тип > <имя функции > (<список формальных параметров>)

Тело функции

1) тип тип возвращаемого функцией значения, с помощью оператора return, если функция не возвращает никакого значения, на место типа следует поместить слово void;

2) имя функции идентификатор, уникальный в программе;

3) список формальных параметров (сигнатура параметров) – заключенный в круглые скобки список спецификаций отдельных формальных параметров перечисляемых через запятую:

< тип параметра> <имя параметра>,

<тип параметра> <имя параметра> = <умалчиваемое значение>,

если параметры отсутствуют, в заголовке после имени функции должны стоять, либо пустые скобки (), либо скобки – (void);

для формального параметра может быть задано, а может и отсутствовать умалчиваемое значение – начальное значение параметра;

4) тело функции это блок или составной оператор, т.е. последовательность определений, описаний и операторов, заключенная в фигурные скобки.

 

Вызов функции

 

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

Форма вызова функции:

 

имя функции (список фактических параметров);

Список фактических параметров может быть пустым, если функция без параметров:

 

имя функции ();

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

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

Если функция не возвращает результата (тип – void), вызов функции представляет собой оператор.

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

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

 

Описание функции (прототип)

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

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

Прототип (описание) функции может внешне почти полностью совпадать с заголовком определения функции:

 

<тип функции> <имя функции>

(<спецификация формальных параметров>);

Отличие описания от заголовка определения функции состоит в следующем:

- наличие '; 'в конце описания – это основное отличие и

- необязательность имен параметров, достаточно через запятые перечислить типы параметров.

 

...

void R (int a, int b, int c)

{ a+=100; b+=100; c+=100;

cout << a<<b<<c<<endl; }

Void main ()

{ int a1=1, b1=2, c1=3;

cout << a1<<b1<<c1<<endl;

R (a1, b1, c1);

// аналогично можнобыло вызвать так: R(1, 2, 3);

// т.к. нас интересуют только значения фактических параметров

cout << a1<<b1<<c1<<endl;

}

Результат:

1 2 3 // значение переменных до вызова функции

101 102 103 // значения формальных параметров

1 2 3 // значения переменных после вызова функции

// функция не изменила значения переменных, являющимися

//фактическими параметрами

 

стек

           
 
     
 


1 2 3 1 2 3

A1 b1 c1 a b c адреса

стек

           
 
 
     


1 2 3 101 102 103

a1 b1 c1 a b c адреса

Рисунок 1 – Схема обмена данными при передаче параметров по значению

...

void RR (int* a, int* b, int*c)

{ * a+=100; *b+=100; * c+= 100;

cout << *a << *b << *c;

}

Void main ()

{ int a1 =1, b1= 2, c1=3;

cout << a1 << b1 <<c1;

RR (&a1, &b1, & c1); //передаем адреса переменных

cout << a1 << b1 <<c1;

}

Результат:

1 2 3 // значения переменных до вызова функции

101 102 103 // изменения параметров в функции

101 102 103 // значения переменных после вызова,

// функция изменила их значения

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

стек

                           
     
       
         
             
 
 


1 2 3 &a1 &b1 &c1

A1 b1 c1 a b c адреса

(указатели)

cтек *a+=100

*b+=100

*c+=100

101 102 103 &a1 &b1 &c1

A1 b1 c1 a b c адреса

Рисунок 2 – Схема обмена данными при передаче параметров по адресу

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

Пример передачи параметров по ссылке:

...

void RRR (int & a, int &b, int & c)

{ a += 100; b+= 100; c+= 100;

cout << a <<b <<c;

}

Void main ()

{ int a1=1, b1 =2, c1=3;

cout << a1 << b1 <<c1;

RRR(a1, b1, c1);

cout << a1 <<b1 << c1;

}

Результат:

1 2 3 // переменные до вызова функции

101 102 103 // изменения параметров в функции

101 102 103 // функция изменила фактические параметры

 

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

 
 


Стек

101 102 103 -знач. переменных после вызова функции

1 2 3 - знач. переменных до вызова функции

a1 b1 c1 - переменные адреса

A b c - ссылки

 

Рисунок 3 – Схема обработки данных функцией при передаче параметров по ссылке

 

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

Если

1) формальные параметры функции являются:

а) скаляры,

б) указатели на скаляры,

в) ссылки на скаляры,

то фактическими параметрами должны быть:

а) значения скаляров,

б) адреса скаляров,

в) имена скаляров (имена участков памяти);

 

2) формальные параметры: массивы или указатели на массивы,

фактические параметры: имена массивов или имена указателей на массивы;

 

3) формальный параметр:

а) определение структуры,

б) указатель на структуру или массив структур

в) ссылка на структуру;

фактический параметр:

а) имя структуры (копирование структуры),

б) адрес (указатель) структуры или указатель на массив структур,

в) имя структуры (работа со структурой без копирования, т.е имя участка памяти, выделенного под структуру);

 

4) формальный параметр – указатель на функцию

фактический параметр – имя функции

 

Void main ()

{ int a[n], min, max;

Randomize ()

for (int i=0; i< n; i++)

a[i] =rand();

minmax (a, min, max);

cout << min << max; }

II) ФОРМАЛЬНЫЕ ПАРАМЕТРЫ - МАССИВЫ, УКАЗАТЕЛИ НА МАССИВЫ

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

 

Формальный параметр- определение массива:

В качестве формальных параметров можно использовать:

1) определение массива с фиксированными границами, например:

float A[5], int B[3][4][2], char S [25];

2) определение одномерного символьного массива с открытой границей:

char S1[];

При работе со строками, то есть с одномерными массивами данных типа char, последний элемент которых имеет известное значение - '\0', нет необходимости передавать размеры массива

3) определение числового или многомерного символьного массива с открытой левой границей и параметр для передачи размера левой границы:

float A[ ], int B[ ][4][2], char S2 [ ][60], и int n

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

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

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

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

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

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

const int n=4, k =5;

void f (float a [ ] [n][k], int m, float & s)

{s = 0; int t =1;

for (int i=0; i< m; i++) for(int j=0; i< n; j++) for (int l=0; l< k; l++)

{ a[i][j][l]=t++; s+= a[i][j][l];}}

Void main ()

{ float s, dat [3][4][5];

f(dat, 3, s); // вызов функции заполняющей массив dat

cout << s;}

 

I) Формальный параметр - указатель:

1) В качестве формальных параметров определяются:

указатель на первый элемент массива любой мерности и второй параметр – общее количество элементов в массиве:

type*p, int n.

Фактическими параметрамив этом случае будут– указатель типа type*, значение которого -адрес первого элемента массива и второй параметр - значение общего количества элементов в массиве. При этом надо помнить, что имя массива любой мерности – это константный указатель, значением которого является адрес первого элемента массива, однако только для одномерного массива имя – есть указатель на элемент массива, для двумерного массива имя массива – это указатель на строку массива и так далее. Чтобы получить указатель на элемент массива для двумерного массива, надо разыменовать имя массива, для трехмерного массива – два раза разыменовать имя массива и так далее. Или решать проблему явным приведением типов указателей.

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

 

#include<iostream.h>

void f (int*a, int*b, int*c, int n, int m)

{int i, j, p;

for (i=0; i < n+m; i++) //формирование неупорядоченного массива

if (i < n) c[i] = a[i];else c[i] = b[i-n];

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

for (i = 0; i < n+m-1; i++)

for (j = n+m - 1; j > i; j --)

if (c[j] < c[j-1]){p= c[j]; c[j] = c[j-1]; c[j-1] = p;}

}

int i, a [ ] = {7,9,5,4,0,2,89,33,73,11},

b [ ] = { 23,87,55,45,4,3,0,6,7,3},

n= sizeof(a) / sizeof (a[0]),

m= sizeof(b) / sizeof (b[0]);

//а)создаваемый массив – статический:

void main (){

int c [sizeof(a) / sizeof (a[0])+ sizeof(b) / sizeof (b[0]) ];

// - выделена память на статический массив

f (a, b, c, n, m);

for(i = 0; i < n+m; i++)

cout << c[i] << " ";

}

//б) создается динамический массив:

Void main ()

{int*x = new int [n+m]; // - выделена память на динамический массив

f (a, b, x, n, m);

for (i =0; i < n+m; i++)

cout << x[i] << " ";

delete [ ] x;

}

2) Формальные параметры - указатели на двумерный массив, размеры которого заранее не известны.

Параметрами являются указатель на массив указателей на строки матрицы: type**p и два значения целого типа: int m - количество этих строк и int n - количество элементов в каждой строке. В этом случае динамически выделяется память и на массив указателей на строки матрицы и на числа в этих строках, таким образом, проводится динамическое выделение памяти на двумерный массив.

В качестве примера определим функцию заполняющую массив – параметр случайными числами:

void mas (int** ptr, int m, int n)

{randomize();

for (int i =0; i < m; i++)

for (int j = 0; j < n; j++)

ptr[i][j] = rand();

}

Void main ()

{float **ptr = new float* [m]; // динамическое выделение памяти

// на массив указателей на строки массива

for(i=0; i< m; i++)

ptr[i] = new float [n]; // динамическое выделение памяти на значения в

//строках массива

mas (ptr,5,6); // вызов функции

for (i=0; i< m; i++) delete ptr[i]; // освобождение памяти на значения в строках

delete [ ] ptr; // освобождение памяти на массив указателей на строки

}

3) Формальные параметры указатели - для передачи многомерного массива. Параметрами являются указатель на подмассив и количество подмассивов в многомерном массиве. При этом размеры подмассива должны быть фиксированы.

<type > (* имя_указателя) [ N1][ N2] [N3]…[NN]; - определение указателя на массив размерностью [N1][N2]…[NN] с элементами type.

Для иллюстрации определим функцию, заполняющую натуральными числами трехмерный массив, состоящий из произвольного числа матриц 3х4:

void mas (int (*lp) [3][4], int n)

{ int i, j, k, t=1;

for (i=0; i < n; i++) {cout << "\n\n";

for (j=0; j < 3; j++) {cout << "\n";

for (k=0; k< 4; k++) { lp[i][j][k] = t++;cout <<lp [i][j][k] << " "; } } } }

Void main ()

{ int i, j, k, n; cin >> n; // вводится количество матриц в трехмерном массиве

int (*tp) [3][4]; // определен указатель на матрицу

tp = new int [ n ] [3][4];

/* выделена динамическая памятьна n матриц, и адрес первой матрицы присвоен указателю tp */

mas (tp, n); // далее можно работать с элементами массива tp[i][j][k]

delete [ ] tp; //освобождение памяти

}

3. Результат функции, возвращаемый с помощью оператора return.

Оператор return - оператор возврата управления программой и значения в точку вызова функции. С помощью этого оператора функция может вернуть одно скалярное значение любого типа. Форма оператора:

return (выражение);

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

К скалярам относятся данные простых стандартных типов, указатели и ссылки. Рассмотрим некоторые возможные результаты работы функций, возвращаемые с помощью оператора return:

1) скалярное значение любого простого типа, например return (5);

2) указатель на скаляр, массив;

3) ссылка - возвращаемый результат функции

 

Void main ()

{ int a[5][4] = {…}, i, j;

int*p = poisk (*a, 20,7); //*a-адрес первого элемента, 20 - общее количество //элементов, ищем число 7

if (p== NULL) cout << "число отсутствует";

else { cout<<(i= (p - *a) / 4); //номер строки

cout<<(j = p - *a – i * 4); }; //номер столбца

}

Void main ()

{float*dat, n; cin >> n; // вводится с клавиатуры количество элементов;

dat = vvod (n); // указателю присваивается результат вызова функции;

for(int i=0; i < n; i++) // поэлементный вывод на экран элементов массива

cout << dat[i] << "\t";

delete dat;} // освобождение памяти;

 

Void main ()

{int n, m,i,j; cin>> n>>m; // размеры массива вводятся с клавиатуры;

int ** Q = mas (m, n); //указателю присваивается результат вызова функции;

…// Q[i][j] - обращение к элементам динамического двумерного массива

//освобождение памяти

for (i=0; i < m; i++) delete Q[i];

delete [ ] Q; }

Результат функции - указатель на подмассив.

 

Определим в качестве примерафункцию, возвращающей значение указателя на подмассив (4х5) элементов типа int, которое является адресом первой матрицы трехмерного массива, сформированного в функции.

#include <iostream.h>

typedef int (*TPM)[4][5];//TPM -тип указателя на матрицу 4х5

TPM fun (int n) // параметр функции – количество подмассивов в массиве

{int i, j, k, t=1;

TPM lp=new int [n][4][5]; // выделяем память на трехмерный массив

for (i=0; i < n; i++){cout << "\n\n";

for (j=0; j < 4; j++){ cout << "\n";

for (k=0; k< 5; k++){lp[i][j][k]=t++; cout <<lp [i][j][k] << " ";} } }

return lp;}

Void main ()

{ int n, i, j, k; cin>>n;

TPM D=fun(n); // вызов функции

//D[i][j][k] - обращение к элементам трехмерного массива

delete []D; // освобождение памяти

}

Void main ()

{ int n =5, a [ ] = { 3, 7, 21, 33, 6};

cout << rmax (n, a)<<endl;

rmax(n,a)=0;

for (int i =0; i <n; i++)

cout << a[i] << " ";}

Результат программы:

3 7 21 0 6

Один из вызовов функции rmax() находится в левой части оператора присваивания, что позволяет занести в элемент новое значение.

 

Функции

Определение, описание и вызовы функций

Программа на языке С++ представляет собой совокупность произвольного количества функций, одна (и единственная) из которых - главная функция с именем main. Выполнение программы начинается и заканчивается выполнением функции main. Выполнение неглавных функций инициируется в главной функции непосредственно или в других функциях, которые сами инициируются в главной.

Функции – это относительно самостоятельные фрагменты программы, оформленные особым образом и снабженные именем.

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

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

По умолчанию все функции внешние (класс памяти extern), доступны во всех файлах программы. При определении функции допускается класс памяти static, если надо чтобы функция использовалась только в данном файле программы.

 

Определение функции

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

Определение состоит из заголовка и тела функции:

 

<тип > <имя функции > (<список формальных параметров>)

Тело функции

1) тип тип возвращаемого функцией значения, с помощью оператора return, если функция не возвращает никакого значения, на место типа следует поместить слово void;

2) имя функции идентификатор, уникальный в программе;

3) список формальных параметров (сигнатура параметров) – заключенный в круглые скобки список спецификаций отдельных формальных параметров перечисляемых через запятую:

< тип параметра> <имя параметра>,

<тип параметра> <имя параметра> = <умалчиваемое значение>,

если параметры отсутствуют, в заголовке после имени функции должны стоять, либо пустые скобки (), либо скобки – (void);

для формального параметра может быть задано, а может и отсутствовать умалчиваемое значение – начальное значение параметра;

4) тело функции это блок или составной оператор, т.е. последовательность определений, описаний и операторов, заключенная в фигурные скобки.

 

Вызов функции

 

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

Форма вызова функции:

 

имя функции (список фактических параметров);

Список фактических параметров может быть пустым, если функция без параметров:

 

имя функции ();

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

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

Если функция не возвращает результата (тип – void), вызов функции представляет собой оператор.

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

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

 

Описание функции (прототип)

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

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

Прототип (описание) функции может внешне почти полностью совпадать с заголовком определения функции:

 

<тип функции> <имя функции>

(<спецификация формальных параметров>);

Отличие описания от заголовка определения функции состоит в следующем:

- наличие '; 'в конце описания – это основное отличие и

- необязательность имен параметров, достаточно через запятые перечислить типы параметров.

 



Поделиться:


Последнее изменение этой страницы: 2017-02-19; просмотров: 385; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.236.57.1 (0.233 с.)