使用浮点文字调用重载函数会产生 'ambiguos' 错误

Calling overloaded function with floating point literal yields 'ambiguos' error

编译以下代码时:

#include <iostream>
using namespace std;

void print(int i){
    cout << i << endl;
}

void print(float i){
    cout << i << endl;
}

int main(){
    print(5);
    print(5.5)
    return 0;
}

我收到错误:

call of overloaded 'print(double)' is ambiguous.

但是,如果我改变

void print(float i){

void print(double i){

代码编译。这是为什么?

尝试不同的练习来理解这一点。删除两个重载中的任何一个都会使程序编译,尽管文字 5.5 没有身份匹配,一个双精度值,它可以隐式转换为 intfloat.

当两个重载都存在时,由于 5.5 可以隐式转换为 intfloat,两者都是可行的。编译器无法在两者之间做出决定,因此出现错误。

在使文字成为 float5.5f 后,我们得到了身份匹配、float 重载并且编译器的决策没有歧义。相反,保留文字 double5.5,将函数原型从 float 更改为 double 也有效,因为这也是身份匹配。

整数版本:

void print(int i)
           ^^^ // This declaration wants an `int` type

浮动版本:

void print(float i)
           ^^^^^ // This declaration wants a `float` type

用法:

print(5); // Calling print with `int`, finds the "Integer version"
print(5.5); // '5.5' is a `double` type, which is neither an `int` type nor a `float` type

由于指定了 double 类型并且没有 double 重载,因此需要转换为 intfloat 才能使用现有的重载。

使用现有的重载:

 print(5.5f); // Use a `float` literal (i.e., this is a `float` type)
 print(static_cast<float>(5.5)); // I'd recommend the former but this works
 print(static_cast<int>(5.5)); // Works but obviously truncates the value

添加新的重载(而不是更新现有的 float 重载):

void print(double i); // A new overload declaration

问题是 5.5 的类型是 double。由于 print 被重载,编译器将寻找最佳匹配以找出调用哪个重载,这个过程称为 overload resolution。这是一组相当复杂的规则,但在您的简单案例中会发生以下情况:

首先,编译器将检查是否完全匹配,即一些 void print(double); 或类似的。

因为这个不存在,所以考虑转化。 double 可以隐式转换为 intfloat,这些转换同样有效。

因此,编译器无法决定它应该调用哪个函数重载并抱怨调用不明确。

正如其他人已经提到的,您可以通过以下方式解决此问题 要么让输入类型完全正确:print(5.5f); 或者添加一个与 double 参数明确匹配的重载,例如

void print (double);
void print (const double&);
template <class T>
void print (T);