我试图重载这些功能,并收到错误消息,说明函数调用不明确。
#include <iostream>
using namespace std;
double volume(int a){
return a*a*a;
}
double volume(int a, int b, int c){
return b*c*a;
}
double volume(int a, int b){
return a*a*b;
}
double volume(double a, double b, double c){
return a*b*c*2.5;
}
int main(){
cout<<volume(2)<<endl;
cout<<volume(2,3)<<endl;
cout<<volume(2,2,3)<<endl;
cout<<volume(2.0,9.7,3)<<endl;//error here
return 0;
}
我得到的错误就是这样
错误:重载的“ volume(double,double,int)”的调用不明确
答案 0 :(得分:3)
当您调用volume(double, double, int)
时,编译器感到困惑,因为编译器应该将double转换为int并调用volume(int, int, int)
,还是应该将int转换为double并调用volume(double, double, double)
。
有3个步骤可以使分辨率超载。
查找候选函数:与被叫函数同名的函数被称为候选函数。在您的情况下,所有名为volume
的函数都是候选函数,因为您调用了volume(..)
找到可行的功能:
一个函数必须经过两个测试才能生效。首先,该函数必须具有与调用中的参数相同数量的参数。 (默认参数除外)。其次,每个参数都必须匹配-或可转换为相应参数的类型。就您而言,volume(int,int,int) and volume(double, double, double)
是可行的功能。
查找最佳匹配项:
重载解析的最后一步确定了与参数最匹配的可行函数。 最好的意思是-精确的类型匹配比需要从参数类型转换为参数类型的匹配要好。在您的情况下,没有最佳匹配。您的通话volume(double, double, int)
与任何可行的功能均不匹配。
让我们看一个比较简单的例子
void foo(int x, int y);
void foo(double x, double y);
假设我们以
拨打电话foo(4.2, 5) //double and int
以上两个foo是候选函数(同名)。
它们都是可行的函数,因为调用可以通过转换进行,并且都带有2个参数。
因此,现在编译器根据参数决定哪个函数最匹配。
如果只有一个函数,则只有一个匹配项:
1。每个参数的匹配都比其他任何可行函数所需的匹配都更糟糕
2。至少有一个参数的匹配度比任何其他可行函数提供的匹配度都要好
因此,当编译器通过可行函数的第一个参数检查第一个参数时,它选择foo(double, double)
是最佳匹配,但是当检查第二个参数时,它发现foo(int, int)
是一个更好的匹配。
因此,通话不明确。每个可行的函数都最好与调用的参数之一匹配。
要解决这种歧义,您需要确保编译器能够找到最佳匹配。因此,您需要显式转换参数。您可以将double转换为int或将last int转换为double。此通话不会有任何歧义:
volume(2.0, 9.7, static_cast<double>(3));
为什么static_cast
?好吧,一般而言,您可以直接编写3.0来代替,它可以正常工作,但是您不能使用某些变量来做
int x = 10;
float a= 2.1, b=4.8;
for(int t=1;t<=x;t++){
volume(a,b,static_cast<double>(t));
//do something with t here
}
注意
通常,您不应尝试在函数调用中显式转换参数以进行重载。 相反,您应该使用要执行的操作创建一个新的重载函数。但是我希望您这样做只是为了学习,一切都很好。在项目中,必须避免这些显式转换。
答案 1 :(得分:2)
GCC扫描程序将3
标记为int
而不是double
将volume(2.0,9.7,3)
更改为volume(2.0,9.7,3.0)
取决于这两个功能:
double volume(double a, double b, double c)
double volume(int a, int b, int c)
您可以拥有volume(2.0,9.7,3.0)
或volume(2,9,3)
如果有任何问题,请在下面评论
答案 2 :(得分:1)
在volume(2.0,9.7,3)
中,2.0
和9.7
均为double
类型的文字值,而3
则为int
类型。
因此,在您提供的volume()
版本中,编译器有两个同样可行的选项;
将两个double
的值转换为int
,并调用接受三个volume()
参数的int
的版本。
将int
的值转换为double
,然后调用接受三个volume()
参数的double
的版本。
这两种选择都是同样可行的-根据该语言的规则,由于两种情况下都存在转换,因此没有理由偏向于另一种选择。因此出现错误消息。
要使编译器变得清晰,您需要通过确保三个参数都具有相同的类型来消除歧义-因为选择是在两个函数之间进行的,而这两个函数都具有相同类型的三个参数({{1 }或double
)。一种方法是提供三个int
值(例如int
)或三个volume(2,9,3)
值(例如double
)。
答案 3 :(得分:0)
编译器尝试进行一些隐式转换(从double
到int
),您在这里有2个匹配项
double volume(int a, int b, int c)
double volume(double a, double b, double c)
将cout<<volume(2.0,9.7,3)<<endl
更改为cout<<volume(2.0,9.7,3.0)<<endl