Перегрузка функций
Слово «открыть» значит разное для двери, книги и банки: что именно делать, понятно по предмету в руках. В C++ так же: несколько функций могут носить одно имя, а нужную компилятор выбирает по аргументам вызова.
Функция 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. Аналогия со словом «открыть» хромает в одном: человек угадывает по смыслу, а компилятор смотрит только на типы аргументов.
Разные списки параметров
Перегрузка — несколько функций с одним именем и разными списками параметров. Списки должны отличаться хотя бы одним из двух:
- типами параметров, как
twice(int)иtwice(double)выше; - числом параметров, как
max(int a, int b)иmax(int a, int b, int c).
Тип результата в этом не участвует. Компилятор выбирает функцию только по аргументам вызова, а результат ещё не получен, когда выбор уже сделан.
Выбор перегрузки
Когда подходят несколько перегрузок, компилятор сравнивает, как аргумент приводится к параметру каждой из них. Способы приведения идут от лучшего к худшему:
- Точное совпадение: тип аргумента равен типу параметра.
- Продвижение: расширение
floatдоdoubleили небольшого целого типа, напримерshort, доint. - Преобразование: остальные смены типа, например
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 — преобразования.
Как компилятор выбирает перегрузку, часто спрашивают на собеседовании. Отвечайте по порядку: точное совпадение, затем продвижение, затем преобразование.
Частая ошибка
Две функции различаются только типом результата:
int parse(int x);
double parse(int x); // ✗error: functions that differ only in their return type cannot be overloadedЭто ошибка компилятора: по вызову parse(5) не понять, какой из двух результатов нужен. Дайте функциям разные имена или разные списки параметров.
Главное
- Перегрузка — функции с одним именем и разными списками параметров: по типам или по числу.
- Тип результата перегрузку не различает: такие функции не компилируются.
- Компилятор предпочитает точное совпадение продвижению, а продвижение — преобразованию.
- Две одинаково хорошие перегрузки делают вызов неоднозначным, и программа не компилируется.
Подпишись, чтобы пройти курс
Курс бесплатный. Войди через Telegram и подпишись на канал — откроются все уроки.