当我写一些关于基本运算符重载的代码时。我发现了这段代码,
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 {
从我看到的其他问题来看,它们都是错误而不是警告。所以我不确定为什么代码仍然有效。希望有人可以向我解释为什么会这样。
提前致谢。
答案 0 :(得分:7)
有一个成员函数operator+(const MyInt&) const
可以像这样调用:
MyInt m1;
MyInt m2;
m1 + m2;
还有一个自由函数operator+(const MyInt&, const MyInt&)
,可以这样调用:
MyInt m1;
MyInt m2;
m1 + m2;
这就是编译器抱怨的原因:语言定义说没有办法决定使用哪一个。选择其中一个。
通常的惯例是只使用自由函数,并通过调用operator+=
来实现它。
警告告诉您接受代码是gcc扩展名。在形式上,编译器不需要拒绝编译错误的代码。唯一的要求是他们发出了一个gcc所做的诊断。完成后,可以继续以编译器编写者认为合理的方式编译代码。依赖此类扩展的代码不可移植。
答案 1 :(得分:3)
从我见过的其他问题来看,这些都是错误而不是警告。
这可能是因为准时程序员告诉他们的编译器不接受你可能跳过的非标准兼容程序。例如,在使用GNU编译器时,它们将使用-pedantic
或更严格的-pedantic-errors
选项。
所以我不确定为什么代码仍然有效。
如果您不告诉编译器不接受非标准代码,那么如果它们支持它作为语言的扩展,它可能会接受它。在这种情况下,标准说过载同样含糊不清并且程序格式不正确,但编译器可能会乐观并猜测您可能要使用的过载,尽管标准说的是。
当您不使用任何选项时,您显示的代码仅使用g ++中的警告进行编译,但使用-pedantic
选项时,这些警告会变为错误。通常-pedantic
仅在使用语言扩展时添加警告,但在这种情况下,它似乎会将警告提升为错误。