编译以下代码时:
#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;
}
我收到错误:
重载'print(double)'的调用是不明确的。
但是,如果我改变
void print(float i){
到
void print(double i){
代码编译。那是为什么?
答案 0 :(得分:5)
尝试不同的练习来理解这一点。删除两个重载中的任何一个都会使程序编译,尽管文字5.5
没有标识匹配,是一个double值,它可以隐式转换为int
或float
。
当两个重载都存在时,由于5.5
可以隐式转换为int
或float
,因此两者都是可行的。编译器无法在两者之间做出决定,因此就是错误。
在将文字设为float
,5.5f
后,我们会进行身份匹配,float
重载,并且对编译器的决策没有歧义。相反,保留文字double
,5.5
,将函数原型从float
更改为double
也是有效的,因为这也是一种身份匹配。
答案 1 :(得分:4)
问题是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);
答案 2 :(得分:3)
整数版本:
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