为什么这个重载函数是模棱两可的?

时间:2018-07-21 04:30:30

标签: c++ function

我试图重载这些功能,并收到错误消息,说明函数调用不明确。

#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)”的调用不明确

4 个答案:

答案 0 :(得分:3)

当您调用volume(double, double, int)时,编译器感到困惑,因为编译器应该将double转换为int并调用volume(int, int, int),还是应该将int转换为double并调用volume(double, double, double)


针对高级读者

超载如何工作?

有3个步骤可以使分辨率超载。

  1. 查找候选函数与被叫函数同名的函数被称为候选函数。在您的情况下,所有名为volume的函数都是候选函数,因为您调用了volume(..)

  2. 找到可行的功能: 一个函数必须经过两个测试才能生效。首先,该函数必须具有与调用中的参数相同数量的参数。 (默认参数除外)。其次,每个参数都必须匹配-或可转换为相应参数的类型。就您而言,volume(int,int,int) and volume(double, double, double)是可行的功能。

  3. 查找最佳匹配项: 重载解析的最后一步确定了与参数最匹配的可行函数。 最好的意思是-精确的类型匹配比需要从参数类型转换为参数类型的匹配要好。在您的情况下,没有最佳匹配。您的通话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.09.7均为double类型的文字值,而3则为int类型。

因此,在您提供的volume()版本中,编译器有两个同样可行的选项;

  • 将两个double的值转换为int,并调用接受三个volume()参数的int的版本。

  • int的值转换为double,然后调用接受三个volume()参数的double的版本。

这两种选择都是同样可行的-根据该语言的规则,由于两种情况下都存在转换,因此没有理由偏向于另一种选择。因此出现错误消息。

要使编译器变得清晰,您需要通过确保三个参数都具有相同的类型来消除歧义-因为选择是在两个函数之间进行的,而这两个函数都具有相同类型的三个参数({{1 }或double)。一种方法是提供三个int值(例如int)或三个volume(2,9,3)值(例如double)。

答案 3 :(得分:0)

编译器尝试进行一些隐式转换(从doubleint),您在这里有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