• Функция f(int)
является подходящей потому, что аргумент типа double
может быть неявно преобразован в параметр типа int
.
• Функция f(double, double)
также является подходящей потому, что для второго параметра задано значение по умолчанию, а первый параметр имеет тип double
, который точно соответствует типу аргумента.
На третьем этапе подбора перегруженной функции выясняется, какая из допустимых функций наилучшим образом соответствует вызову. Этот процесс анализирует каждый аргумент вызова и выбирает подходящую функцию (или функции), для которой соответствие параметра аргументу является наилучшим. Подробно критерии наилучшего соответствия рассматриваются в следующем разделе, а пока достаточно знать, что чем ближе типы аргумента и параметра друг к другу, тем лучше соответствие.
В данном случае существует только один (явный) аргумент, который имеет тип double
. При вызове версии f(int)
аргумент преобразуется из типа double
в тип int
. Вторая подходящая функция, f(double, double)
, точно соответствует типу этого аргумента. Поскольку точное соответствие лучше соответствия требующего преобразования, компилятор предпочитает версию с двумя параметрами типа double
. Для второго, недостающего аргумента компилятор добавит аргумент по умолчанию.
Если у функции два или несколько аргументов, подбор подходящей версии усложняется. Предположим, что функции имеют то же имя f
, но анализируется следующий вызов:
f(42, 2.56);
Набор подходящих функций выявляется, как прежде. Компилятор выбирает те версии функции, которые имеют необходимое количество параметров, типы которых соответствуют типам аргументов. В данном случае в набор подходящих вошли функции f(int, int)
и f(double, double)
. Затем компилятор перебирает аргументы один за одним и определяет, какая из версий функций имеет наилучшее соответствие. Наилучше соответствующая функция та, для которой единственной выполняются следующие условия.
• Соответствие по каждому аргументу не хуже, чем у остальных подходящих функций.
• По крайней мере у одного аргумента соответствие лучше, чем у остальных подходящих функций.
Если после просмотра всех аргументов не было найдено ни одной функции, которая считалась бы наилучше соответствующей, компилятор сообщает об ошибке неоднозначности вызова.
В рассматриваемом примере вызова анализ лишь первого аргумента для версии f(int, int)
функции f()
обнаруживает точное соответствие. При анализе второй версии функции f()
оказывается, что аргумент 42
типа int
следует преобразовать в значение типа double
. Соответствие в результате встроенного преобразования хуже, чем точное. Таким образом, рассматривая только этот параметр, лучше соответствует та версия функции f()
, которая обладает двумя параметрами типа int
, а не двумя параметрами типа double
.
Но при переходе ко второму аргументу оказывается, что версия функции f()
с двумя параметрами типа double
точно соответствует аргументу 2.56
. Вызов версии функции f()
с двумя параметрами типа int
потребует преобразования аргумента 2.56
из типа double
в тип int
. Таким образом, при рассмотрении только второго параметра версия f(double, double)
функции f()
имеет лучшее соответствие.
Компилятор отклонит этот вызов, поскольку он неоднозначен: каждая подходящая функция является лучшим соответствием по одному из аргументов. Было бы заманчиво обеспечить соответствие за счет явного приведения типов (см. раздел 4.11.3) одного из аргументов. Но в хорошо спроектированных системах в приведении аргументов не должно быть необходимости.
Упражнение 6.49. Что такое функция-кандидат? Что такое подходящая функция?
Упражнение 6.50. С учетом приведенных в начале раздела объявлений функции f()
перечислите подходящие функции для каждого из следующих вызовов. Укажите наилучше соответствие, или если его нет, то из-за отсутствия соответствия или неоднозначности вызова?
(a) f(2.56, 42) (b) f(42) (с) f(42, 0) (d) f(2.56, 3.14)
Упражнение 6.51. Напишите все четыре версии функции f()
. Каждая из них должна выводить собственное сообщение. Проверьте свои ответы на предыдущее упражнение. Если ответы были неправильными, перечитайте этот раздел и выясните, почему вы ошиблись.