Перейти к содержимому
Теория · Функции · урок 7 из 13

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

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

Функция int twice(int x) удваивает целые числа, а для 1.25 нужна такая же функция с double. Придумывать ей другое имя не обязательно: в C++ обе функции могут называться twice:

C++
#include <iostream>

int twice(int x) {
    return x * 2;
}

double twice(double x) {
    return x * 2;
}

int main() {
    std::cout << twice(21) << ' ' << twice(1.25) << '\n';  // 42 2.5
}

Для 21 компилятор вызывает версию с int, а для 1.25 — версию с double. Аналогия со словом «открыть» хромает в одном: человек угадывает по смыслу, а компилятор смотрит только на типы аргументов.

Разные списки параметров

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

  • типами параметров, как twice(int) и twice(double) выше;
  • числом параметров, как max(int a, int b) и max(int a, int b, int c).

Тип результата в этом не участвует. Компилятор выбирает функцию только по аргументам вызова, а результат ещё не получен, когда выбор уже сделан.

Выбор перегрузки

Когда подходят несколько перегрузок, компилятор сравнивает, как аргумент приводится к параметру каждой из них. Способы приведения идут от лучшего к худшему:

  1. Точное совпадение: тип аргумента равен типу параметра.
  2. Продвижение: расширение float до double или небольшого целого типа, например short, до int.
  3. Преобразование: остальные смены типа, например float → int или int → double.

Аргумент типа short попадёт в twice(int): до int его продвигают, а до double преобразуют.

Литерал 2.5f имеет тип float, а 2.5 — double. Поэтому twice(2.5f) вызовет twice(double): до double значение float продвигают, а до int преобразуют.

Если лучших перегрузок две и они одинаково хороши, вызов неоднозначен, и программа не компилируется. Так случится с аргументом типа long: и long → int, и long → double — преобразования.

Как компилятор выбирает перегрузку, часто спрашивают на собеседовании. Отвечайте по порядку: точное совпадение, затем продвижение, затем преобразование.

Частая ошибка

Две функции различаются только типом результата:

C++
int parse(int x);
double parse(int x);  // ✗
TEXT
error: functions that differ only in their return type cannot be overloaded

Это ошибка компилятора: по вызову parse(5) не понять, какой из двух результатов нужен. Дайте функциям разные имена или разные списки параметров.

Главное

  • Перегрузка — функции с одним именем и разными списками параметров: по типам или по числу.
  • Тип результата перегрузку не различает: такие функции не компилируются.
  • Компилятор предпочитает точное совпадение продвижению, а продвижение — преобразованию.
  • Две одинаково хорошие перегрузки делают вызов неоднозначным, и программа не компилируется.

Подпишись, чтобы пройти курс

Курс бесплатный. Войди через Telegram и подпишись на канал — откроются все уроки.

Войти другим способом