为什么这种重载函数是不明确的

Why does this overloaded functions is ambiguous?

本文关键字:不明确 函数 重载 为什么      更新时间:2023-10-16

我试图重载这些函数,但收到一个错误,说函数调用不明确。

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

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


适用于高级读卡器

过载是如何工作的

解决过载问题有三个步骤。

  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,是候选函数(同名)。

它们都是可行的函数,因为可以通过转换进行调用,并且都有两个参数。

所以现在编译器通过一个参数一个参数地决定哪个函数最匹配。

如果只有并且只有一个功能,则存在匹配:

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 
}

注意

一般情况下,您不应该尝试在函数调用中显式转换参数以进行重载。相反,你应该用你试图做的事情来创建一个新的重载函数。但我希望你这样做只是为了学习,一切都好。在项目中,必须避免这些显式转换。

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)

如果有任何问题,请在下面评论

volume(2.0,9.7,3)中,2.09.7都是double类型的文字值,但3int类型的。

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

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

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

这两个选项都同样可行-根据语言规则,没有理由选择其中一个,因为在这两种情况下都有转换。因此出现了错误消息。

为了使编译器变得明确,您需要通过确保三个参数都具有相同的类型来消除歧义,因为可以在两个函数之间进行选择,这两个函数都具有相同类型的三个参数(doubleint)。一种方式是提供三个int值(例如,volume(2,9,3))或三个double值(例如volume(2.0, 9.7, 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