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

Определение

Перегрузка функций — это механизм С++, благодаря которому функции с разным количеством или типами параметров могут иметь одинаковое имя (идентификатор).

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

Например, допустимо определить пользовательские функции:

void print(int); //печать целого
void print(const char*); //печать символьной Си-строки

С точки зрения компилятора, единственное, что данные функции имеют общего между собой — это имена. Язык не накладывает в связи с этим никаких ограничений на программиста, и эти функции могут делать совершенно разные вещи.

Пример перегрузки функции abs()

Создадим несколько собственных реализаций функции модуля числа:

int abs(int x)
{
    cout << "(function A)";
    return x > 0 ? x : -x;
}
double abs(double x)
{
    cout << "(function B)";
    return (1 - 2*(x<0))*x;
}
char abs(char x)
{
    cout << "(function C)";
    return x > 0 ? x : -x;
}
double abs(double x, double y)
{
    cout << "(function D)";
    return sqrt(x*x + y*y);
}

int main()
{
    cout << abs(-3) << endl;
    cout << int(abs(char(-3L))) << endl;
    cout << abs(-3.0) << endl;
    cout << abs('0') << endl;
    cout << abs(3, 4) << endl;
    return 0;
}

Когда вызывается функция abs(), компилятор должен определить какую из функций с именем abs() использовать. Идея состоит в том, чтобы использовать функцию с наиболее подходящими аргументами и выдать сообщение об ошибке, если таковой не найдено.

Критерии соответствия параметров при перегрузке функций

Критерии наилучшего соответствия параметров выстроены в следующем порядке:

  1. точное соответствие типов;
  2. соответствие, достигаемое "продвижением" ("повышением в чине") интегральных типов (например, bool в int, char в int, short в int или float в double);
  3. соответствие, достигаемое путем стандартных преобразований (int double, double int double long double, указателей на производные типы на указатели в базовые, произвольны указателей к void*);
  4. соответствие, достигаемое при помощи преобразований, определенных пользователем;
  5. соответствие за счет многоточий в объявлении функции (эллипсис).

Если соответствие может быть получено двумя или более способами на одном и том же уровне критериев, вызов считается неоднозначным и отвергается.

Замечание

Функции, объявленные в различных областях видимости, не являются перегруженными. Если нужно, чтобы область действия перегрузки пересекала области видимости классов или пространство имен, можно воспользоваться директивой using.

Перегрузка и возвращаемые типы

Возвращаемые типы не участвуют в разрешении перегрузки.

int overloading_type1(int x, int y) {return 0;}
int overloading_type1(int x) {return 0;}

int overloading_type2(int x) {return 0;}
int overloading_type2(double x) {return 0;}

int overloading_type3(int x) {return 0;}
double overloading_type3(int x) {return 0;}

Первые два типа перегрузки допустимы, а третий тип, хотя и встречается в других языках программирования, в языке С++ недопустим.