ISO C++ 表示这些是模棱两可的运算符重载



当我编写一些关于基本运算符重载的代码时。我发现了这段代码,

struct MyInt {
  public:
    MyInt()  : data() { };
    MyInt(int val) : data(val) { }
    MyInt& operator++() {
      ++data;
      return (*this);
    }
    MyInt operator++(int) {
      MyInt copy = *this;
      ++data;
      return copy;
    }
    MyInt& operator+=(const MyInt& rhs) {
        data += rhs.data;
        return *this;
    }
    MyInt operator+(const MyInt& rhs) const {
      MyInt copy = *this;
      copy += rhs;
      return copy;
    }
    int data;
};

这些都很好,直到我在类声明后添加它

MyInt operator+(const MyInt& lhs, const MyInt& rhs)
{
  MyInt copy = lhs;
  copy.data += rhs.data;
  return copy;
}

有了这个主要声明

int main () {
  MyInt mi = 10;
  MyInt mi2 = 11;
  MyInt mi3 = mi++ + ++mi2;
  mi3 += mi2;
}

当我尝试编译时,g++ 向我抛出了这个警告

warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second:
   MyInt mi3 = mi++ + ++mi2;
                        ^
note: candidate 1: MyInt operator+(const MyInt&, const MyInt&)
 MyInt operator+(const MyInt& lhs, const MyInt& rhs)
       ^
note: candidate 2: MyInt MyInt::operator+(const MyInt&) const
     MyInt operator+(const MyInt& rhs) const {

从我看到的其他问题来看,它们都是错误而不是警告。所以我不太确定为什么它的代码仍然有效。希望有人能向我解释为什么会发生这种情况。

提前谢谢。

有一个

成员函数operator+(const MyInt&) const可以像这样调用:

MyInt m1;
MyInt m2;
m1 + m2;

还有一个自由函数operator+(const MyInt&, const MyInt&),可以这样调用:

MyInt m1;
MyInt m2;
m1 + m2;

这就是编译器抱怨的原因:语言定义说没有办法决定使用哪一个。选择一个或另一个。

通常的约定是只有 free 函数,并通过调用 operator+= 来实现它。

警告告诉您接受代码是 gcc 扩展。从形式上讲,编译器不需要拒绝编译错误的代码。唯一的要求是他们发出诊断,GCC就是这样做的。完成此操作后,可以自由地继续以编译器编写者认为合理的某种方式编译代码。依赖于此类扩展的代码不可移植。

从我看到的其他问题来看,它们都是错误而不是警告。

这可能是因为准时的程序员告诉他们的编译器不要接受非标准兼容的程序,而您可能已经跳过了。例如,他们在使用 GNU 编译器时会使用-pedantic甚至更严格的-pedantic-errors选项。

所以我不太确定为什么它的代码仍然有效。

如果你不告诉你的编译器不接受非标准代码,那么如果他们支持它作为语言的扩展,它可能会接受它。在这种情况下,标准说重载同样模棱两可,程序格式不正确,但编译器可能会乐观地猜测你可能打算使用的重载,尽管标准说了什么。

您显示的代码恰好在不使用任何选项时在 g++ 中仅使用警告进行编译,但使用 -pedantic 选项时,这些警告将成为错误。通常-pedantic仅在使用语言扩展时添加警告,但在这种情况下,它似乎将警告提升为错误。

最新更新