Прототип (описание, объявление) функции

 

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

Общий вид прототипа следующий:

 

тип имя_функции([список_формальных_параметров])[,

имя_функции2([список2_формальных_параметров])];

 

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

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

 

// Листинг 9.1

#include <iostream>

#include <conio.h>

using namespace std;

 

// Компилятор игнорирует имена переменных

// в прототипе функции

 

// Прототип, имя параметра указывать не нужно

bool IsDigit(char);

// Прототипы функций

void f1(int), f2(double), f3(int, int);

 

int main() {

if (IsDigit('w')) cout << " Digit " << endl;

else cout << " Not digit " << endl;

if (IsDigit('5')) cout << " Digit " << endl;

else cout << " Not digit " << endl;

// 119 – код символа 'w', 53 – символа '5'

if (IsDigit(119)) cout << " Digit " << endl;

else cout << " Not digit " << endl;

if (IsDigit(53)) cout << " Digit " << endl;

else cout << " Not digit " << endl;

f1('w');

f1(100);

f1(-3.54);

f2('w');

f2(100);

f2(-3.54);

f3(9, 5);

f3(2.5, 2.5);

return 0;

}

 

bool IsDigit(char c) {

cout <<"sizeof(c) = "<< sizeof(c) <<" c = "<< c;

return (c >= '0' && c <= '9');

}

 

void f1(int n) {

cout <<"1 sizeof(n) = "<< sizeof(n)

<< " n = " << n << endl;

}

 

void f2(double d) {

cout <<"2 sizeof(d) = "<< sizeof(d)

<< " d = " << d << endl;

}

 

void f3(int n, int m) {

cout <<"3 sizeof(n) = "<< sizeof(n)

<<" n*m = "<<n*m<< endl;

}

 

Результат выполнения программы:

 

sizeof(c) = 1 c = w Not digit

sizeof(c) = 1 c = 5 Digit

sizeof(c) = 1 c = w Not digit

1 sizeof(n) = 4 n = 119

1 sizeof(n) = 4 n = 100

1 sizeof(n) = 4 n = -3

2 sizeof(n) = 8 d = 119

2 sizeof(n) = 8 d = 100

2 sizeof(n) = 8 d = -3.54

3 sizeof(n) = 4 n*m = 45

3 sizeof(n) = 4 n*m = 4

 

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

Различают:

- список формальных параметров – список параметров в определении (и объявлении) функции;

- список фактических параметров – список значений, передаваемых в функцию при её вызове.

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

 

Рекурсия

 

Рекурсивной называют функцию, которая в своём теле вызывает саму себя (прямая рекурсия). Когда две или более функций вызывают друг друга, возникает косвенная рекурсия.

 

Пример: вычисление факториала числа (0! = 1 и 1! = 1)

n! = 1×2×3×(n–1)×n

// Листинг 9.2

#include <iostream>

using namespace std;

 

int factorial(int); // Прототип функции

 

int main() {

int k = 4;

cout <<"k="<< k <<"; k! ="<< factorial(k) <<endl;

return 0; }

 

int factorial(int n) {

if (n < 0) {

cout << "ERROR!" << endl; return -1;

}

// Рекурсивный вызов

return (n > 1)? n*factorial(n–1): 1;

}

 

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

Очень важно при организации рекурсивных функций предусмотреть проверку условия выхода из рекурсии. Иначе можно «улететь» в бесконечную рекурсию. Любую рекурсивную функцию можно реализовать без использования рекурсии.

Достоинство рекурсии – компактная запись.

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

 


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: