Как определить, какая перегруженная функция вызывается? - PullRequest
4 голосов
/ 31 декабря 2011
#include <iostream>
#include <cmath>
using namespace std;

float f (int a, int b) {
    return (a + b);
}

float f (float a, float b) {
    return (round(a + b));
}

int main ()
{
    cout << "Hello World!" << endl;
    int int1 = 1;
    int int2 = 2;
    float float1 = 1.2f;
    float float2 = 1.4f;
    cout << f(int1, int2) << endl;     // output: 3
    cout << f(float1, float2) << endl; // output: 2
    cout << f(int1, float2) << endl;   // output: 2
    return 0;
}
  1. Почему в последнем выводе используется второе определение f?

  2. В общем, как определить, какое определение перегруженной функции будет использоваться, если нет точного соответствия числа и типов аргументов между определениями функции и вызовом функции?

Ответы [ 3 ]

4 голосов
/ 31 декабря 2011

После попытки определить в стандарте, почему одна перегрузка предпочтительнее другой, я пришел к выводу, что не должно быть, ни одна перегрузка не имеет лучшей последовательности преобразования, чем другая в случае f( int1, float2 ) и кода не должен компилироваться. Если ваш компилятор принимает его, в реализации может быть ошибка.

Что касается второго вопроса, стандарт определяет преобразования, которые можно использовать для сопоставления вызова функции, а также определяет rank для тех преобразований, которые служат в качестве частичного упорядочения (называемого * 1006). * Лучшее преобразование, чем ). Компилятор всегда выбирает преобразование best , и если преобразования best нет, то программа работает неправильно, как в примере.

Проверка неоднозначности кода с различными компиляторами:

НКА:

conv.cpp:22: error: call of overloaded ‘f(int&, float&)’ is ambiguous
conv.cpp:5: note: candidates are: float f(int, int)
conv.cpp:9: note:                 float f(float, float)

лязг:

conv.cpp:22:13: error: call to 'f' is ambiguous
    cout << f(int1, float2) << endl;   // output: 2
            ^
conv.cpp:5:7: note: candidate function
float f (int a, int b) {
      ^
conv.cpp:9:7: note: candidate function
float f (float a, float b) {
      ^

MSVS 2010 (спасибо Xeo):

error C2666: 'f' : 2 overloads have similar conversions
          src\main.cpp(2): could be 'void f(int,int)'
          src\main.cpp(1): or       'void f(float,float)'
          while trying to match the argument list '(int, float)'
0 голосов
/ 31 декабря 2011

Проще говоря, если вы конвертируете int в float, вы не теряете информацию;если вы конвертируете float в int, вы теряете десятичную часть числа.Если компилятор не может найти точное соответствие перегрузки, он выберет тот, который вызывает наименьшую потерю информации.

0 голосов
/ 31 декабря 2011

Все, что вам нужно знать и многое другое: http://www.learncpp.com/cpp-tutorial/76-function-overloading/

По сути, выбирается второе, потому что если точное совпадение невозможно и совпадение по продвижению невозможно, сопоставление по преобразованию (первого параметра от int до float) выполняется.

...