Один из способов, которым достигается реализация полиморфизма в языке С++, заключается в использовании перезагрузки функций. В 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. Тем не менее эти операции совершенно различны, и использование перегрузки функций в подобных ситуациях противоречит самой идее перегрузки функций. В частности, перегрузку функций следует применять только для сходных между собой операций.