Листинг 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;
}
Еще один примечательный способ использования ссылок или указателей демонстрирует следующий листинг, приведенный для варианта с ссылками. Здесь возвращаемое функцией значение является ссылкой, в связи с чем над самим вызовом могут выполняться различные операции.