为什么传递一个long long时,会调用一个有两个类型为double的参数的重载函数?

问题描述 投票:9回答:1

这两个重载函数是我写的。

int func(int, int) {
    return 1;
}

int func(double, double) {
    return 2;
}

当我用明显的两种调用方式调用它们时,即: func(1, 1)func(1.0, 1.0),第一个和第二个重载函数分别被调用,而当我尝试调用 func(1, 1.0) 它给了我一个错误,但当我施放了 1long long,我没有出错,而且第二个重载是被调用的。

#include <iostream>
int main()
{
    std::cout << func(1, 1); // outputs 1.
    std::cout << func(1.0, 1.0); // outputs 2.
    // std::cout << func(1, 1.0); // erroneous.
    std::cout << func((long long)1, 1.0); // outputs 2.
}

为什么会出现这种情况呢?起初,我以为是由于某种推广的原因,但我试着用两个float调用第三个重载,但我无法让它被调用,就像调用 func((int)1, 1.0f). 我不知道为什么会不一样,我也不知道为什么第二个重载被调用时,一个 long long 被传递了。

c++ double overloading overload-resolution
1个回答
45
投票

从一个重载集中选择哪个函数来调用(也就是 重载解析)取决于(部分地)函数调用的多少个参数必须经过一个叫 隐式转换,以及需要什么样的转换。

与你的例子相关的规则是。

对于每一对可行的函数F1和F2 从第i个参数到第i个参数的隐式转换序列进行排序 以确定哪一个更好。

如果F1的所有参数的隐式转换不比F2的所有参数的隐式转换差,并且......F1至少有一个参数的隐式转换比F2的该参数对应的隐式转换好,则确定F1是比F2更好的函数。

所以给定重载集。

int func(int, int);        // #1
int func(double, double);  // #2 

让我们考虑以下的调用

func(1, 1);    // perfect match for #1, so #1 is chosen

func(1., 1.);  // perfect match for #2, so #2 is chosen

func(1., 1);   // could call #1 by converting 1st argument to int 
               // (floating-integral conversion)

               // could call #2 by converting 2nd argument to double 
               // (floating-integral conversion)

               // error: ambiguous (equal number of conversions needed for both #1 and #2)

func(1ll, 1.); // could call #1 by converting both arguments to ints
               // (integral conversion for 1st argument, floating-integral conversion for 2nd argument)

               // could call #2 by converting just 1st argument to double
               // (floating-integral conversion for 1st argument)

               // for the 2nd parameter, #2 is ranked as a better choice, 
               // since it has a better implicit conversion sequence for #2
               // and so #2 is chosen (even though both #1 and #2 are tied for the 1st argument)

现在让我们在其中加入第三个重载。

int func(float, float);  // #3

现在当你调用时

func(1, 1.f);  // could call #1 by converting 2nd argument to int
               // (floating-integral conversion for 2nd argument)

               // could call #2 by converting 1st argument to double, and converting 2nd argument to double 
               // (floating-integral conversion for 1st argument, and floating-point promotion for 2nd argument)

               // could call #3 by converting 1st argument to float  
               // (floating-integral conversion for 2nd argument)

               // error: ambiguous (equal number of conversions needed for #1, #2 and #3)
© www.soinside.com 2019 - 2024. All rights reserved.