C++“运算符”的不明确重载

C++ ambiguous overload for ‘operator ’

本文关键字:运算符 不明确 重载 C++      更新时间:2023-10-16

我在这里读了几篇关于这种错误的帖子,但我无法解决这个......很快我定义了运算符 int 和函数 f,编译失败。我测试了几件事,但我无法解决问题......谢谢

ex1.cpp: In function ‘int main(int, char**)’:
ex1.cpp:35:13: error: ambiguous overload for ‘operator+’ in ‘a + 4’
ex1.cpp:35:13: note: candidates are:
ex1.cpp:35:13: note: operator+(int, int) <built-in>
In file included from ex1.cpp:3:0:
Fraccao.h:41:9: note: Fraccao operator+(const Fraccao&, const Fraccao&)
ex1.cpp:38:13: error: ambiguous overload for ‘operator+’ in ‘4 + a’
ex1.cpp:38:13: note: candidates are:
ex1.cpp:38:13: note: operator+(int, int) <built-in>
In file included from ex1.cpp:3:0:
Fraccao.h:41:9: note: Fraccao operator+(const Fraccao&, const Fraccao&)

班级:

class Fraccao {
    int numerador;
    int denominador;
public:
    Fraccao(int num = 0, int deno = 1) : numerador(num), denominador(deno) {}
    Fraccao & operator+=(const Fraccao &fra);
    Fraccao & operator*=(const Fraccao &fra);
    operator int() const;
    const Fraccao & operator++();
    const Fraccao operator++(int);
    string getAsString() const;
};
Fraccao operator +(const Fraccao &a, const Fraccao &b);
ostream & operator<<(ostream & saida, const Fraccao & fra);

在我的主上:

void func(int n) {
    cout << n; // 
}
int main(int argc, char** argv) {
    //...
    d = a + b;
    const Fraccao h(7, 3);
    func(h);
    return 0;
}

您似乎没有发布实际导致错误的代码。我想它看起来像

Fraccao a;
Fraccao b = a + 4;
Fraccao c = 4 + a;

问题是你的类允许隐式转换int;所以a + 4可以是

int(a) + 4

a + Fraccao(4)

没有理由选择一个而不是另一个。要解决歧义,您可以:

  • 使转换明确,如上所述;或
  • 声明构造函数或转换运算符(甚至两者)explicit以便只能隐式执行一个(甚至两个)转换。

您可以通过多种方式解决问题:

  • 禁止从intFraccao的隐式转换:使构造函数explicit
  • 禁止从Fraccaoint的隐式转换:使转换运算符explicit

  • 在呼叫者端手动转换,给定Fraccao f; int i; int(f)+if+Fraccao(i)

  • 提供额外的重载来解决歧义:

Fraccao operator +(const Fraccao &a, const Fraccao &b);
Fraccao operator +(const int a, const Fraccao &b);
Fraccao operator +(const Fraccao &a, const int b);

后者可能意味着您还需要:

Fraccao & operator+=(const Fraccao &fra);
Fraccao & operator+=(const int i);

最后,如果你想要后者,你可以使用像Boost.Operator或我的df.operator这样的库来支持你,避免一遍又一遍地编写相同的转发器。

编译器看到两种解释a + 4的方法。它可以将4转换为类型为 Fraccao 的对象并使用 operator+(const Fraccao&, const Fraccao&),也可以使用成员转换运算符将a转换为类型 int,并向结果添加4。重载规则使这变得模棱两可,这就是编译器所抱怨的。一般来说,正如@gx_在评论中所说,出现这个问题是因为两个方向都有转换。如果用explicit (C++11) 标记operator int(),则代码就可以了。