Перегрузка и аргументы по умолчанию
Функция int twice(int x) удваивает целые числа, а для 1.25 нужна такая же функция с double. Придумывать ей другое имя не обязательно: в C++ обе функции могут называться twice:
#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) — их числом. Тип результата в этом не участвует: функции, которые различаются только им, не компилируются.
int parse(int x);
double parse(int x); // ✗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) — значение, которое компилятор подставит, если в вызове этого аргумента нет:
#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). Перегрузка здесь не нужна: функция одна, а вызвать её можно с одним аргументом или с двумя.
Частая ошибка
Значение по умолчанию задают параметру, за которым идёт параметр без такого значения:
int power(int base = 2, int exp); // ✗error: missing default argument on parameter 'exp'Это ошибка компилятора: после параметра со значением по умолчанию все следующие тоже должны его иметь. Иначе по вызову power(3) не понять, какой параметр получил 3. Перенесите такие параметры в конец списка.