Листинг 4.3. Перегрузка функций

 

#include <iostream>

 

using namespace std;

 

//Функция вывода целых значений значений.

void output (int val, int base = 10)

{

if (base == 10)

cout << dec << val << endl;

 

if (base == 16)

cout << hex << val << endl;

}

 

//Функция вывода дробных значений значений.

void output (double val, …)

{

cout << fixed << val << endl;

}

 

int main (void)

{

int base, ival;

cin >> ival >> base;

 

//вызов целочисленной версии с параметром по умолчанию;

output( ival );

 

//вызов целочисленной версии с заданным параметром;

output( ival, base );

 

double dval;

cin >> dval;

 

//вызов дробной версии;

output( dval );

 

return 0;

}

 

4.2. Рекурсия

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

 

Листинг 4.4. Рекурсия.

 

#include <iostream>

 

using namespace std;

 

//Рекурсивное вычисление факториала.

int factorial (int val)

{

return !val ? 1 : val * factorial( val-1 );

}

 

//Рекурсивное возведение в степень.

double power (double val, int deg)

{

return !deg ? 1 : val * power( val, deg-1 );

}

 

int main (void)

{

int ival;

cin >> ival;

 

cout << factorial(ival) << endl;

 

double dval;

cin >> dval;

 

cout << power(dval, ival) << endl;

 

return 0;

}

 

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

 

4.3. Указатели и ссылки

4.3.1. Передаваемые параметры

Параметрами функции могут быть не только копии каких-либо объектов, но и сами эти объекты. Подобный механизм реализуется посредством параметров – указателей и параметров – ссылок. Типичным примером является передача функции массива в качестве параметра. Для больших массивов копирование значений всех элементов весьма трудоемко и неэффективно. Вместо этого, массив передается через указатель на его первый элемент и значение количества его элементов или указатель на последний.

 

Листинг 4.5. Указатели, как передаваемые параметры.

 

#include <iostream>

#include <cstring>

 

using namespace std;

 

//функция удаления последнего элемента из строки

//как из стека с возвращением удаляемого символа;

char pop (char *str)

{

int length = strlen(str);

char poped = *(str + length — 1); //сохранение последнего элемента;

*(str + length - 1) = *(str + length); //удаление последнего элемента;

return poped;

}

 

int main (void)

{

char *str = new char[20]; //резервирование памяти под строку;

cin >> str;

cout << pop(str) << endl; //удаление последнего символа;

cout << str << endl;

 

return 0;

}

 

Другим примером использования параметров – указателей является передача структур.

 

4.3.2. Возвращаемые значения

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

 

Листинг 4.6. Указатели, как возвращаемые значения.

 

#include <iostream>

#include <cstring>

 

using namespace std;

 

//функция удаления последнего элемента из строки

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

char* pop (char *str)

{

int length = strlen(str);

*(str + length - 1) = *(str + length); //удаление последнего элемента;

return str;

}

 

int main (void)

{

char *str = new char[20]; //резервирование памяти под строку;

cin >> str;

cout << pop(str) << endl; //удаление последнего символа;

 

return 0;

}

 

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