简体   繁体   中英

How to determine which overloaded function is called?

#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. Why the last output uses the second definition of f ?

  2. In general, how to determine which overloaded function definition will be used, when there is not an exact matching of the number and types of the arguments between the function definitions and the function call?

After trying to determine in the standard why should one overload preferred over the other I have come to the conclusion that it shouldn't, no overload has a better conversion sequence than the other in the case of f( int1, float2 ) and the code should not compile. If your compiler is accepting it, there might be a bug in the implementation.

As of the second question, the standard defines the conversions that can be used to match a call to a function and it also defines a rank for those conversions that serves as a partial ordering (called better conversion than ). The compiler will always choose the best conversion, and if there is no best conversion then the program is ill formed as in the example.

Verification of the ambiguity of the code with different compilers:

GCC:

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)

clang:

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 (Thanks to 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)'

All you need to know and more: http://www.learncpp.com/cpp-tutorial/76-function-overloading/

Essentially the second one is selected because if no exact match is possible and no match by promotion is possible, a match by conversion (of the first parameter from int to float ) is done.

In very simple terms, if you convert int to float you lose no information; if you convert float to int you loose the decimal part of the number. If the compiler cannot find an exact overload match, it will choose the one that causes the least loss of information.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM