使用浮点文字调用重载函数会产生 '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
没有身份匹配,一个双精度值,它可以隐式转换为 int
或 float
.
当两个重载都存在时,由于 5.5
可以隐式转换为 int
或 float
,两者都是可行的。编译器无法在两者之间做出决定,因此出现错误。
在使文字成为 float
、5.5f
后,我们得到了身份匹配、float
重载并且编译器的决策没有歧义。相反,保留文字 double
、5.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
重载,因此需要转换为 int
或 float
才能使用现有的重载。
使用现有的重载:
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
可以隐式转换为 int
和 float
,这些转换同样有效。
因此,编译器无法决定它应该调用哪个函数重载并抱怨调用不明确。
正如其他人已经提到的,您可以通过以下方式解决此问题
要么让输入类型完全正确:print(5.5f);
或者添加一个与 double
参数明确匹配的重载,例如
void print (double);
void print (const double&);
template <class T>
void print (T);
编译以下代码时:
#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
没有身份匹配,一个双精度值,它可以隐式转换为 int
或 float
.
当两个重载都存在时,由于 5.5
可以隐式转换为 int
或 float
,两者都是可行的。编译器无法在两者之间做出决定,因此出现错误。
在使文字成为 float
、5.5f
后,我们得到了身份匹配、float
重载并且编译器的决策没有歧义。相反,保留文字 double
、5.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
重载,因此需要转换为 int
或 float
才能使用现有的重载。
使用现有的重载:
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
可以隐式转换为 int
和 float
,这些转换同样有效。
因此,编译器无法决定它应该调用哪个函数重载并抱怨调用不明确。
正如其他人已经提到的,您可以通过以下方式解决此问题
要么让输入类型完全正确:print(5.5f);
或者添加一个与 double
参数明确匹配的重载,例如
void print (double);
void print (const double&);
template <class T>
void print (T);