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

Перегрузка и аргументы по умолчанию

Функция 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.

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

Перегрузка (overloading) — несколько функций с одним именем и разными списками параметров. Списки должны отличаться числом параметров или их типами. Функции twice выше различаются типом параметра, а max(int a, int b) и max(int a, int b, int c) — их числом. Тип результата в этом не участвует: функции, которые различаются только им, не компилируются.

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

Компилятор выбирает функцию только по аргументам вызова, а по parse(5) не понять, какой из двух результатов нужен.

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

Если точного совпадения нет, компилятор сравнивает, как аргумент приводится к параметру каждой перегрузки: точное совпадение лучше продвижения (promotion), а продвижение лучше преобразования. Продвижение — расширение float до double или небольшого целого типа, например short, до int. Остальные смены типа, вроде float → int, — преобразования.

Поэтому аргумент типа short попадёт в twice(int), а не в twice(double). Литерал 2.5f имеет тип float, а 2.5 — double.

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

Необязательные аргументы

Параметру можно задать аргумент по умолчанию (default argument) — значение, которое компилятор подставит, если в вызове этого аргумента нет:

C++
#include <iostream>

int power(int base, int exp = 2) {
    int result = 1;
    for (int i = 0; i < exp; ++i) {
        result *= base;
    }
    return result;
}

int main() {
    std::cout << power(5) << ' ' << power(2, 10) << '\n';  // 25 1024
}

Вызов power(5) компилятор превращает в power(5, 2). Перегрузка здесь не нужна: функция одна, а вызвать её можно с одним аргументом или с двумя.

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

Значение по умолчанию задают параметру, за которым идёт параметр без такого значения:

C++
int power(int base = 2, int exp);  // ✗
TEXT
error: missing default argument on parameter 'exp'

Это ошибка компилятора: после параметра со значением по умолчанию все следующие тоже должны его иметь. Иначе по вызову power(3) не понять, какой параметр получил 3. Перенесите такие параметры в конец списка.