有人可以向我解释此错误吗? 这是代码:
class O{
unsigned x;
unsigned y;
public:
O(unsigned x_ ,unsigned y_): x(x_), y(y_){
};
O& operator+= ( O & object){
x += object.x;
}
};
class A {
O item;
public:
A(O i): item(i){;
}
void fun() const{
O j(2,3);
j += item;
}
};
int main(){
return 0;
}
当我尝试编译时,出现此错误:
In member function 'void A::fun() const':
[Error] no match for 'operator+=' (operand types are 'O' and 'const O')
[Note] candidate is:
[Note] O& O::operator+=(O&)
[Note] no known conversion for argument 1 from 'const O' to 'O&'
有人可以向我解释吗?如果将const限定词添加到+ =运算符的参数中,则会进行编译。所以我认为问题在于我正在const函数fun()中将对item的引用传递给+ =运算符,该运算符是非const的。谁能解释我为什么这是非法的,以及如何避免犯这种错误,例如,在使用const限定词等时要遵循一些经验法则。?
答案 0 :(得分:4)
此成员函数
void fun() const{
O j(2,3);
j += item;
}
是常量成员函数。因此,调用该函数的对象的成员被视为常量成员,特别是在这种情况下,数据成员项被视为声明为
const O item;
在此表达式中
j += item;
使用了成员函数
O& operator+= ( O & object){
x += object.x;
}
接受对类型O的对象的非常量引用。因此,实际上,您正在尝试将非常量引用绑定到常量对象。因此,编译器会发出错误消息。
上述运算符的参数应使用限定符const声明,并具有return语句,例如
O& operator+= ( const O & object) {
x += object.x;
return *this;
}
答案 1 :(得分:3)
在许多地方,const
关键字是一个保证,[某些代码]不会改变标记为const
的事物的状态。相比之下,缺少关键字必须解释为[某些代码] 可能会改变事物的状态。
编译器会检查这些承诺是否是有根据的,并抱怨它们是否是必需的。
在这种情况下,您有一个声明
O& O::operator+= (O & object);
您不要在其中保证将参数object
保持不变。而且,由于这是一个参考论点,因此您不能保证将所提及的内容保留下来。
但是您尝试从上下文中调用该操作
void A::fun() const;
这样做的 承诺保持调用对象的状态不变,然后使用其成员之一(A::item
)作为O::operator+
的参数。
编译器抱怨您在一个地方答应保持A::item
不变,而在另一个地方没有保证。
由于O::operator+=
实际上并没有改变其参数,因此您可以通过将签名更改为
O& O::operator+= (const O & object);
完成并撒粉。