【问题标题】:Ambiguous Overload For Operator运算符的模糊重载
【发布时间】:2014-04-13 18:22:05
【问题描述】:

我正在研究 CBigInt 类。 CBigInt 类是具有无限长度的整数类。它看起来像这样:

class CBigInt{
  public:
    string number;
    int sign;
    CBigInt()
    CBigInt(const int a);
    CBigInt(const string a);
    CBigInt& operator = (const string rhs);
    CBigInt& operator=(const CBigInt& rhs);
    CBigInt& operator=(int rhs );
    CBigInt& operator+=(const CBigInt& rhs);
    CBigInt operator+(const CBigInt& rhs);
    CBigInt& operator+=(const string rhs);
    CBigInt operator+(const string rhs);
    CBigInt& operator *=(const CBigInt& rhs);
    CBigInt operator*(const CBigInt& rhs);
    CBigInt& operator*=(const string rhs);
    CBigInt operator*(const string rhs);
    friend ostream& operator<<(ostream& off, const CBigInt& big);
    friend istream& operator>>(istream& in,  CBigInt& big );
}

定义了所有运算符,并且在我能想到的所有示例中都可以找到作品,除了这个:

CBigInt       a, b;
a *= 0; 

编译器无法决定使用两个函数中的哪一个:

CBigInt& operator *=(const CBigInt& rhs);
or
CBigInt& operator *=(const string rhs);

我阅读了一些非常相似的问题,但没有太大帮助。

错误:

/home/michal/Desktop/prog/big/main.cpp||In function ‘int main()’:|
/home/michal/Desktop/prog/big/main.cpp|345|error: ambiguous overload for ‘operator*=’ in ‘a *= 0’|
/home/michal/Desktop/prog/big/main.cpp|345|note: candidates are:|
/home/michal/Desktop/prog/big/main.cpp|198|note: CBigInt& CBigInt::operator*=(const CBigInt&)|
/home/michal/Desktop/prog/big/main.cpp|247|note: CBigInt& CBigInt::operator*=(std::string)|
||=== Build finished: 4 errors, 0 warnings ===|

【问题讨论】:

  • 不要使用运算符重载,特别是不要过度使用它,特别是不要与语法重载结合使用。只是我的两分钱;)
  • @DanielDaranas,我想说它使类的行为更加自然,但在这种情况下,如果使用 CBigInt(someInt) 太多,请将其限制为 CBigInt *= CBigInt 或其他整数类型。 CBigInt *= std::string 看起来很别扭。
  • 它的学校作业......它用于学习超载
  • @DanielDaranas:不知道你来自什么糟糕的语言,但在 C++ 世界里,我们一直都在使用这样的重载。
  • pastebin.com/jutYr9ma 我不知道 ... = 现在似乎完全错了.. 我错过了什么吗?

标签: c++ overloading operator-keyword


【解决方案1】:

只需删除此运算符

CBigInt operator*(const string rhs);

有运营商就够了

CBigInt operator*(const CBigInt& rhs);

因为类有两个转换构造函数

CBigInt(const int a);
CBigInt(const string a);

所以而不是一组运算符

CBigInt& operator = (const string rhs);
CBigInt& operator=(const CBigInt& rhs);
CBigInt& operator=(int rhs );
CBigInt& operator+=(const CBigInt& rhs);
CBigInt operator+(const CBigInt& rhs);
CBigInt& operator+=(const string rhs);
CBigInt operator+(const string rhs);
CBigInt& operator *=(const CBigInt& rhs);
CBigInt operator*(const CBigInt& rhs);
CBigInt& operator*=(const string rhs);
CBigInt operator*(const string rhs);

你可以写

CBigInt& operator=(const CBigInt& rhs);
CBigInt& operator+=(const CBigInt& rhs);
CBigInt operator+(const CBigInt& rhs);
CBigInt& operator *=(const CBigInt& rhs);
CBigInt operator*(const CBigInt& rhs);

同时改变构造函数

CBigInt(const int a);
CBigInt(const string a);

CBigInt( int a);
CBigInt(const string &a);

考虑到代码包含拼写错误。您在

之后错过了分号
   CBigInt()

类定义的右大括号。

比如这段代码编译成功

#include <iostream>
#include <string>

class CBigInt{
  public:
    std::string number;
    int sign;
    CBigInt() {}
    CBigInt(const int a) {}
    CBigInt(const std::string &a) {}
    CBigInt& operator=(const CBigInt& rhs) { return *this; }
    CBigInt& operator+=(const CBigInt& rhs);
    CBigInt operator+(const CBigInt& rhs);
    CBigInt& operator *=(const CBigInt& rhs) { return *this; }
    CBigInt operator*(const CBigInt& rhs);
    friend std::ostream& operator<<(std::ostream& off, const CBigInt& big);
    friend std::istream& operator>>(std::istream& in,  CBigInt& big );
};

int main() 
{
    CBigInt i1, i2, i3;

    i1 = i2 *= i3;

    i1 *= 0;

    i1 *= std::string( "Hello" );

    return 0;
}

如果您需要使用字符串文字,那么您可以添加重载运算符

    CBigInt& operator *=(const char *rhs) { return *this; }

【讨论】:

  • 当我以这种方式编辑我的代码时。它给出/home/michal/Desktop/prog/big/main.cpp||在函数'int main()'中:| /home/michal/Desktop/prog/big/main.cpp|311|错误:'a += 20'中的'operator+='不匹配| /home/michal/Desktop/prog/big/main.cpp|311|注意:候选人是:| /home/michal/Desktop/prog/big/main.cpp|53|注意:CBigInt& CBigInt::operator+=(const CBigInt&)| /home/michal/Desktop/prog/big/main.cpp|53|注意:没有已知的参数 1 从“int”到“const CBigInt&”的转换|
  • @user3512285,这些构造函数没有理由出现该错误。
  • 您的非变异二元运算符未正确标记const。此外,您可以认真考虑单独的 raue 引用重载是否值得。
  • @DeadMG 那么我应该如何解决它。我不太明白。
  • 我需要 ' i1 *= "1534"; ' 去工作。这就是为什么我有那些字符串运算符。
【解决方案2】:

简单的解决方法是a *= CBigInt(0);

【讨论】:

  • 我正在为学校作业写这门课。并且不能影响测试数据。
【解决方案3】:

由于没有operator*= 函数具有int 作为参数类型,编译器必须决定可以使用哪些其他函数。它发现int 可以转换为CBigIntstring。编译器无法解决这种歧义。因此错误。你可以通过明确来解决这个问题。我想你想使用

a *= CBigInt(0);

【讨论】:

  • 错误:只有构造函数的声明可以是“显式”的|
  • @user3512285,这与这个答案无关。它所说的只是明确的,意思是CBigInt(0)而不是0
  • 我的错。但无论如何我都不能说清楚,因为测试数据不是我的。
  • @user3512285,该分配是否强制执行确切的int 转换构造函数以及operator*=s 完全如图所示?这样就无法解决问题,负责您任务的人会提供更多帮助。
【解决方案4】:

简单的解决方案是将转换运算符标记为显式:

explicit CBigInt(const std::string &a) {}

这将防止转换被考虑用于运算符 *= 的重载解析。

如果您同时定义了转换运算符和可能使用该转换运算符的重载,那么您将度过一段糟糕的时光。通常,应避免隐式转换,除非它们非常必要且非常简单。

使用内置类型系统作为指导。如果 C++ 标准需要在等价类型之间进行显式转换(它会在 int 和 char* 之间进行),那么您的转换运算符不应该是隐式的。

【讨论】:

    猜你喜欢
    • 2019-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-15
    • 1970-01-01
    • 1970-01-01
    • 2022-10-01
    • 1970-01-01
    相关资源
    最近更新 更多