“运算符”的 C++ 模棱两可的重载

Posted

技术标签:

【中文标题】“运算符”的 C++ 模棱两可的重载【英文标题】:C++ ambiguous overload for ‘operator ’ 【发布时间】:2013-11-18 02:32:51 【问题描述】:

我在这里阅读了几篇关于此类错误的帖子,但我无法解决这个错误... 很快我定义了运算符 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;

【问题讨论】:

你在哪里声明的? d = a + b 是什么意思?放置变量声明,以便我们可以了解您在做什么 当你有一个类可以从 and 隐式转换为 int... 时会发生这种情况 【参考方案1】:

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

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

问题是您的类允许与int 进行隐式转换;所以a + 4 可以是

int(a) + 4

a + Fraccao(4)

没有理由选择其中之一。要解决歧义,您可以:

使转换显式,如上;或 声明构造函数或转换运算符(甚至两者)explicit,以便只能隐式完成一个(或什至都不)转换。

【讨论】:

Daniel Frey 建议使操作符接收 (Fraccao, int) 的构造函数显式,反之亦然。谢谢【参考方案2】:

您有多种选择来解决您的问题:

禁止从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.Operators 或我的 df.operators 这样的库来支持你,避免一遍又一遍地编写相同的转发器。

【讨论】:

【参考方案3】:

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

【讨论】:

以上是关于“运算符”的 C++ 模棱两可的重载的主要内容,如果未能解决你的问题,请参考以下文章

C#,多个 == 运算符重载,没有模棱两可的空值检查

c语言,c++,哪些运算符不能重载?

C++ 运算符重载

C++运算符重载时要遵循的规则

C++运算符重载

C++运算符重载