Ответ
Разрешение перегрузки (overload resolution) — это процесс выбора наиболее подходящей функции для данного вызова. Он происходит в несколько чётких этапов.
1. Поиск имён (Name Lookup): Компилятор находит все функции с указанным именем в текущей области видимости (с учётом пространств имён и ADL — Argument-Dependent Lookup).
2. Формирование набора кандидатов: Из найденных функций отбираются те, которые можно вызвать с данным числом аргументов (после учёта аргументов по умолчанию).
3. Ранжирование кандидатов: Для каждого кандидата определяется, насколько хорошо типы аргументов соответствуют типам параметров. Устанавливается «ранг» преобразования:
| Ранг преобразования | Пример (вызов f(arg)) |
Приоритет |
|---|---|---|
| Точное совпадение | Типы идентичны, включая const/volatile. f(int) ← f(42) |
Наивысший |
| Продвижение (Promotion) | Целочисленные: char→int, bool→int. f(int) ← f('a') |
Высокий |
| Стандартное преобразование | int→double, указатель→bool. f(double) ← f(42) |
Средний |
| Пользовательское преобразование | Через конструктор или оператор. f(MyClass) ← f(42) |
Низкий |
Многоточие (...) |
f(int, ...) ← f(42, 1.0) |
Наинизший |
4. Выбор наилучшей функции:
- Выбирается функция, для которой все преобразования аргументов имеют не хуже ранг, чем у любого другого кандидата.
- Если для какого-то кандидата есть хотя бы один аргумент с лучшим рангом преобразования, он побеждает.
- Если два кандидата одинаково хороши — возникает неоднозначность (ambiguity), и компилятор выдаёт ошибку.
Пример с ранжированием:
void process(int); // (1)
void process(double); // (2)
void process(long, int=0);// (3)
process(10); // Выбирает (1): точное совпадение (int ← int).
process(10.0f); // Выбирает (2): float → double (стандартное) лучше, чем float → int (стандартное) или float → long (стандартное). Ранги равны, но стандартные преобразования имеют разную «стоимость».
process(10L); // Ошибка неоднозначности: (2) требует long → double, (3) — точное совпадение по первому аргументу. Ни одна функция не лучше другой по всем аргументам.
Важные нюансы:
- Шаблонные функции участвуют в перегрузке. Нешаблонная функция обычно приоритетнее шаблонной при прочих равных.
- Учитываются ссылки, rvalue-ссылки и
const. - Преобразования, требующие
const_cast, не рассматриваются.