首页 > 解决方案 > 为什么这个重载的函数是模棱两可的?

问题描述

我试图重载这些函数并得到错误说函数调用不明确。

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

标签: c++function

解决方案


当您调用volume(double, double, int)as should compiler convert doubles to ints and call volume(int, int, int)or should convert int to double and call时,编译器会感到困惑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)是一个更好的匹配。

因此,该调用是模棱两可的。每个可行函数都更好地匹配调用的参数之一。


解决方案

要解决这种歧义,您需要确保编译器能够找到最佳匹配。因此,您需要显式转换参数。在您的情况下,您可以将双精度数转换为整数或将最后一个整数转换为双精度数。这个调用不会模棱两可:

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 
}

笔记

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


推荐阅读