История вопроса
C++ с самого начала проектировался как язык, поддерживающий перегрузку функций — возможность объявлять несколько функций с одинаковым именем, но разными параметрами. Это позволяет создавать читаемый и удобный API.
Проблема
Когда функций с одинаковым именем становится много, компилятору нужно выбрать подходящую реализацию из всех перегруженных, учитывая типы аргументов, конвертации, параметры по умолчанию и ссылки. При небрежной перегрузке возникают неоднозначности и трудноуловимые ошибки.
Решение
Компилятор выбирает функцию на основе наилучшего совпадения последовательности аргументов, точности соответствия типа и минимальных преобразований. Но стоит учитывать нюансы: если есть значимые конвертации или аргументы по умолчанию, можно неожиданно получить неоднозначность.
Пример кода:
void foo(int x); void foo(double x); void foo(int x, int y = 0); foo(5); // вызовет void foo(int x), потому что это точное попадание foo(5.2); // вызовет void foo(double x) foo(5, 6); // вызовет void foo(int x, int y)
Ключевые особенности:
Можно ли перегрузить функции только по возвращаемому типу?
Нет. Перегрузка возможна ТОЛЬКО по типу и числу параметров, возвращаемый тип не участвует в разрешении перегрузки.
int foo(); double foo(); // Ошибка: перегрузка только по return type невозможна!
Как компилятор выбирает, какую перегруженную функцию вызвать, если все параметры приводимы?
Компилятор выбирает "наилучшее совпадение" — функцию, для которой требуется минимальное число преобразований типов, либо точное совпадение. Если существует двусмысленность, код не скомпилируется.
void bar(int); void bar(long); bar(1); // int точное попадание: вызовется bar(int)
Можно ли смешивать перегрузку по аргументам по умолчанию и обычную перегрузку?
Можно, но можно получить неоднозначность вызова, если сигнатуры функций перекрываются.
void test(int x); void test(int x, int y = 10); test(5); // Ошибка: неоднозначность — обе подходят
В библиотеке встречаются перегруженные функции с перекрывающимися аргументами по умолчанию, что приводит к ошибкам компиляции при обновлении кода.
Плюсы:
Минусы:
В проекте введено соглашение — не смешивать перегрузки с аргументами по умолчанию, либо использовать только одну функцию с default-значениями либо чисто перегружать по уникальным параметрам.
Плюсы:
Минусы: