Программирование на C и C++

Онлайн справочник программиста на C и C++

Перезагрузка функций

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

#include <iostream.h>
// sqr_it перегружается три раза
int sqr_it (int i);
double sqr_it (double d);
long sqr_it(long l);
int main()
{
cout << sqr_it(10) << "\n";
cout << sqr_it (11.0) << "\n";
cout << sqr_it(9L) << "\n";
return 0;
}
int sqr_it (int i)
{
cout << "Inside the sqr_it() function that uses ";
cout << "an integer argument.\n ";
return i*i;
}
double sqr_it(double d)
{
cout << "Inside the sqr_it() function that uses ";
cout << "a double argument.\n ";
return d*d;
}
long sqr_it(long l)
{
cout << "Inside the sqr_it() function that uses ";
cout << "a long argument.\n ";
return l*l;
}

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

Перегрузка функций важна потому, что она помогает в решении проблемы сложности. Рассмот­рим следующий пример, иллюстрирующий, как это происходит. Стандартная библиотека Borland C++ содержит функции itoa(), ltoa() и ultoa(). Все вместе эти функции преобразуют числа различ­ных типов (целые, длинные целые и беззнаковые целые) в их строковые эквиваленты. Хотя эти фун­кции выполняют почти что одинаковые действия, в языке С для выполнения такого преобразования необходимо использовать три различных имени, что делает ситуацию более сложной, чем она есть на самом деле. Хотя основная концепция каждой функции одна и та же, программист вынужден запоминать и работать с каждой функцией отдельно. В противоположность этому в С++ можно использовать одно и то же имя, такое как numtoa(), для каждой из трех функций. Таким образом, имя numtoa() выражает общие действия, которые необходимо выполнить. Задача выбора специфи­ческой версии функции возлагается на компилятор. Этот выбор зависит от специфической ситуа­ции. Программисту необходимо только запомнить общее действие, которое необходимо выпол­нить. Таким образом, применение полиморфизма в данном примере позволяет сократить число используемых функций с трех до одной. Если взглянуть на эту концепцию более широко, то мож­но увидеть, каким образом полиморфизм помогает работать с очень сложными программами.

В следующем примере иллюстрируется практическая ситуация, в которой перегрузка функций оказывает существенную помощь. Языки С и С++ не содержат библиотечных функций, которые выдают подсказку пользователю, чтобы он ввел данные, а затем ждут от него ответа. В представ­ленной ниже программе создаются три такие функции, с именем prompt(), осуществляющие ввод данных типов int, double и long:

#include <iostream.h>
void prompt (char *str, int *i);
void prompt (char *str, double *d);
void prompt (char *str, long *l);
int main()
{
int i;
double d;
long I;
prompt ("Enter an integer: ",&i);
prompt ("Enter a double: ",&d);
prompt ("Enter a long: ",&l);
cout << i << " " << d << " " « l;
return 0;
}
void prompt (char *str, int *i)
{
cout << str;
cin >> *i;
}
void prompt (char *str, double *d)
{
cout << str;
cin >> *d;
}
void prompt (char *str, long *l)
{
cout << str;
cin >> *l;
}

Хотя можно использовать одно и то же имя для перегрузки функций, выполняющих совершен­но различные задачи, делать этого не следует. Например, можно использовать имя sqr_it() для создания функций, возвращающих квадрат целых чисел и квадратный корень чисел типа double. Тем не менее эти операции совершенно различны, и использование перегрузки функций в подоб­ных ситуациях противоречит самой идее перегрузки функций. В частности, перегрузку функций следует применять только для сходных между собой операций.