В этом разделе мы узнаем об одной из самых удивительных возможностей языка C++ — перегрузке функций. В C++ несколько функций могут иметь одинаковые имена, но при условии, что их параметры будут различными. Такую ситуацию называют перегрузкой функций (function overloading), а функции, которые в ней задействованы, — перегруженными (overloaded). Перегрузка функций — один из способов реализации полиморфизма в C++.
Рассмотрим простой пример перегрузки функций.
// "Трехкратная" перегрузка функции f().
#include <iostream>
using namespace std;
void f(int i); // один целочисленный параметр
void f(int i, int j); // два целочисленных параметра
void f(double k); // один параметр типа double
int main()
{
f (10); // вызов функции f(int)
f(10, 20); // вызов функции f (int, int)
f(12.23); // вызов функции f(double)
return 0;
}
void f(int i)
{
cout << "В функции f(int), i равно " << i << '\n';
}
void f(int i, int j)
{
cout << "В функции f(int, int), i равно " << i;
cout << ", j равно " << j << '\n';
}
void f(double k)
{
cout << "В функции f(double), k равно " << k << ' \n';
}
При выполнении эта программа генерирует следующие результаты.
В функции f(int), i равно 10
В функции f(int, int), i равно 10, j равно 20
В функции f(double), к равно 12.23
Как видите, функция f() перегружается три раза. Первая версия принимает один целочисленный параметр, вторая — два целочисленных параметра, а третья — один double-параметр. Поскольку списки параметров для всех трех версий различны, компилятор обладает достаточной информацией, чтобы вызвать правильную версию каждой функции. В общем случае для создания перегрузки некоторой функции достаточно объявить различные ее версии.
Для определения того, какую версию перегруженной функции вызвать, компилятор использует тип и/или количество аргументов. Таким образом, перегруженные функции должны отличаться типами и/или числом параметров. Несмотря на то что перегруженные методы могут отличаться и типами возвращаемых значений, этого вида информации недостаточно для C++, чтобы во всех случаях компилятор мог решить, какую именно функцию нужно вызвать.
Чтобы лучше понять выигрыш от перегрузки функций, рассмотрим три функции из стандартной библиотеки: abs(), labs() и fabs(). Они были впервые определены в языке С, а затем ради совместимости включены в C++. Функция abs() возвращает абсолютное значение (модуль) целого числа, функция labs() возвращает модуль длинного целочисленного значения (типа long), a fabs() — модуль значения с плавающей точкой (типа double). Поскольку язык С не поддерживает перегрузку функций, каждая функция должна иметь собственное имя, несмотря на то, что все три функции выполняют, по сути, одно и то же действие. Это делает ситуацию сложнее, чем она есть на самом деле. Другими словами, при одних и тех же действиях программисту необходимо помнить имена всех трех (в данном случае) функций вместо одного. Но в C++, как показано в следующем примере, можно использовать только одно имя для всех трех функций.
// Создание функций myabs() — перегруженной версии функции abs().
#include <iostream>
using namespace std;
// Функция myabs() перегружается тремя способами.
int myabs(int i);
double myabs(double d);
long myabs(long l);
int main()
{
cout << myabs(-10) << "\n";
cout << myabs(-11.0) << "\n";
cout << myabs(-9L) << "\n";
return 0;
}