对重载函数错误的奇怪模糊调用

时间:2013-05-17 05:42:36

标签: c++ visual-c++

我正在尝试

void function(int y,int w)
{
    printf("int function");

}


void function(float y,float w)
{
    printf("float function");
}


int main()
{
    function(1.2,2.2);
    return 0;
}

我收到错误错误,如..

error C2668: 'function' : ambiguous call to overloaded function

当我尝试拨打function(1.2,2)function(1,2.2)时,它会打印为“ int function

请说明function(float y,float w)何时被召唤?

11 个答案:

答案 0 :(得分:71)

查看来自gcc的错误消息:

a.cpp:16: error: call of overloaded ‘function(double, double)’ is ambiguous
a.cpp:3: note: candidates are: void function(int, int)
a.cpp:9: note:                 void function(float, float)

对任一函数的调用都需要截断,这就是为什么两者都不优先于另一个。我怀疑你真的想要void function(double y,double w)。请记住,在 C / C ++ 中,文字和参数传递的默认浮点类型是双,而不是 float

<强>更新

如果您确实不想将功能签名浮动更改为 double ,则可以始终使用文字< / em>键入 float 。如果将后缀 f 添加到浮点数,它们将被键入float。

您的示例将是function(1.2f, 2f)function(1, 2.2f)

答案 1 :(得分:35)

什么是运算符重载?

Sbi's着名的Operator overloading faq非常详细地回答了这个问题。

为什么OP中的两个function版本允许存在?

请注意,它们使用不同的函数参数 types intfloat),因此有资格作为有效的函数重载。

什么是重载分辨率?

这是通过编译器实现选择最合适的函数/运算符的过程。如果存在一个最好的可行函数并且是唯一的,则重载解析成功并将其作为结果产生。否则,重载解析失败,并且调用被视为格式错误,编译器提供诊断。编译器使用implicit conversion sequence来查找最佳匹配函数。

C ++ 03标准13.3.3.1隐式转换:

  

隐式转换序列是一系列转换,用于将函数调用中的参数转换为被调用函数的相应参数的类型。

隐式转换序列可以是以下类别之一:

  • 标准转换序列(13.3.3.1.1)
  • 用户定义的转换序列(13.3.3.1.2)
  • 省略号转换序列(13.3.3.1.3)

请注意,对这些中的每一个进行排名以确定最佳可行功能。最好的可行功能是所有参数都具有比所有其他可行功能更好或相等排名的隐式转换序列的功能。标准在各个部分中详细描述了每一个。标准转换序列与此案例相关,总结如下:

enter image description here

有足够的重载分辨率背景。
让我们来看看OP中的代码示例:

function(1.2,2.2);

重要规则: 1.22.2是文字,它们被视为double数据类型。

在隐式转换序列映射期间:
具有double类型的函数参数文字都需要转换等级来调用floatint版本,并且没有一个是比其他更好的匹配,他们得分转换排名完全相同。编译器无法检测到最佳可行匹配,并且报告了歧义。

function(1.2,2);

隐式转换序列映射期间:
其中一个函数参数2int函数版本具有完全匹配,而另一个1.2具有转换等级。对于以float为参数的函数,两个参数的隐式转换序列均为转换等级
因此,int版本得分比float版本更好,并且是最佳匹配并被调用的函数。

如何解决歧义错误?

如果您不希望隐式转换序列映射将您抛弃,只需提供函数并以这种方式调用它们,以便参数是完全匹配。由于精确匹配得分高于其他所有人,因此您可以确定所需的函数被调用。在您的情况下,有两种方法可以做到这一点:

解决方案1:

  

调用该函数,使参数与可用函数完全匹配。

function(1.2f,2.2f);

由于1.2f2.2f被视为float类型,因此它们与float函数版本完全匹配。

解决方案2:

  

提供一个函数重载,它与被调用函数中的参数类型完全匹配。

function(double, double){}

由于1.22.2被视为double,因此被调用的函数与此重载完全匹配。

答案 2 :(得分:7)

如果您不想(如接受的答案中所述):

  • 使用浮点文字,例如1.2f
  • 或将现有的float重置更改为double

您可以添加另一个调用浮点数的重载:

void function(double y, double w)
{
    function((float)y, (float)w);
}

main中的代码现在将调用上述函数,该函数将调用float重载。

答案 3 :(得分:5)

上例中的函数重载有不明确的调用,因为返回类型相同,函数调用中的第二个参数是double,可以视为int或float,因此编译器会混淆执行哪个函数。 / p>

答案 4 :(得分:4)

我希望这有帮助 所有组合的代码都是自我解释的

你需要发送两个float来调用一个float函数

#include<iostream>
#include<stdio.h>

using namespace std;

//when arguments are both int
void function(int y,int w) {
    printf("int function\n");
}

//when arguments are both double
void function(double y, double w) {
    printf("double function\n");
}

//when arguments are both float
void function(float y, float w) {
    printf("float function\n");
}

//when arguments are int and float
void function(int y, float x) {
    printf("int float function\n");
}

//when arguments are float and int
void function(float y,int w) {
    printf("float int function\n");
}

//when arguments are int and double
void function(int y, double w) {
    printf("int double function\n");
}

//when arguments are double and int
void function(double y, int x) {
    printf("double int function\n");
}

//when arguments are double and float
void function(double y, float x) {
    printf("double float function\n");
}

//when arguments are float and double
void function(float y, double x) {
    printf("float double function\n");
}



int main(int argc, char *argv[]) {
    function(1.2,2.2);
    function(1.2f,2.2f);
    function(1,2);
    function(1.2,2.2f);
    function(1.2f,2.2);
    function(1,2.2);
    function(1,2.2f);
    function(1.2,2);
    function(1.2f,2);
    return 0;
}

答案 5 :(得分:2)

当将基本类型作为参数发送给函数时,如果要发送的基元类型与它请求的基本类型不完全相同,则应始终将其转换为请求的基元类型。

int main()
{
    function(1.3f,                    2.4f);
    function(1.3f,                    static_cast<float>(2.4));
    function(static_cast<float>(1.3), static_cast<float>(2.4));
    function(static_cast<float>(1),   static_cast<float>(2));
    return 0;
}

答案 6 :(得分:2)

默认情况下,decimal被视为double。如果你想要十进制浮点数,你用f后缀。 在您调用函数(1.2,2.2)的示例中,编译器将您传递给它的值视为double,因此您在函数签名中会遇到不匹配。

function(1.2,1.2) ====> function(double,double)

如果要保留函数签名,则需要在传递浮点字面值时使用浮点后缀。

function(1.2f,1.2f) ====>   function(float,float).

如果您对了解浮点文字更感兴趣,可以参考

Why floating point value such as 3.14 are considered as double by default in MSVC?

答案 7 :(得分:1)

就像其他人所说的那样,你将双打赋予你为花车设计的重载功能。重载本身没有任何错误。

这是正确使用重载函数(注意数字后面的'f'):

function(1.0f, 2.0f);

答案 8 :(得分:0)

function(1.2,2.2);

这些数字不是花车,而是双打。所以这段代码说:

double p1 = 1.2;
double p2 = 2.2;
void (*fn)(double /*decltype(p1)*/, double /*decltype(p2)*/) = function;

编译器现在正在寻找一个需要两个双打的“功能”。没有完全匹配。接下来它会查找一个函数,该函数接受可以从双精度转换的参数。有两场比赛。

function(int, int);
function(float, float);

您有几种选择。

  1. 添加完全匹配重载。

    void函数(double,double) {     printf(“double function \ n”); }

  2. 使用cast。

    function(static_cast(1.2),static_cast(2.2));

  3. 使用浮点数而不是双打符号调用“function”:

    功能(1.2f,2.2f);

答案 9 :(得分:0)

试试这个

#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.5f);
    return 0;
}

在函数重载时浮点数可能与其他同名函数中的其他数据类型冲突,那么可能这就是它的结束。我试过它。

答案 10 :(得分:-1)

想象一下你的论据将如何传递。

如果将它作为1.2和2.2传递给(int,int)函数,那么它将被截断为1和2。

如果将它作为1.2和2.2传递给(float,float),它将按原样处理。

所以这里的模糊性就在这里。

我找到了两种方法来解决这个问题。 首先是使用文字: -

int main()
{
        function(1.2F,2.2F);
    return 0;
}

其次,以及我喜欢的方式,它始终有效(也可用于C ++的默认转换和升级)。 对于int: -

int main()
{
int a=1.2, b=2.2;
    function(a,b);
    return 0;
}

对于Float: -

int main()
{
float a=1.2, b=2.2;
    function(a,b);
    return 0;
}

所以不要使用实际的DIGITS。最好先将它们声明为类型,然后重载!

现在看,如果你把它作为(1.2,2) or (1,2.2)发送,那么编译器只需将它发送到int函数就可以了。 但是,要将它发送到float函数,编译器必须将2提升为float。只有在找不到匹配项时才会进行促销。

参见: - 使用C ++进行计算机科学 Sumita Arora 章节:功能重载