我有以下代码被破坏了。我可以通过修改代码中的某些行来修复它(请参阅注释)。问题的原因是什么?
#include <iostream>
using namespace std;
class Number{
public:
int n;
Number(int a):n(a){}
//when I change the following to
//friend Number& operator++(Number& source, int i)
//then it compiles fine and correct value is printed
friend Number operator++(Number& source, int i){
++source.n;
return source;
}
};
int main() {
Number x(5);
x++++; //error: no 'operator++(int)' declared for postfix '++' [-fpermissive]
cout<<x.n;
return 0;
}
答案 0 :(得分:16)
您尝试将第二个++
应用于第一次调用返回的临时对象。但是,操作数必须通过引用传递,并且您不能将临时绑定到非常量 lvalue 引用。
你可能不想“修复”这个,因为没有理由修改这样的临时值。但是,您应该在递增之前返回值的副本,以提供预期的增量后行为。
前缀运算符应返回一个引用,该引用可以愉快地绑定到另一个引用,以便++++x;
按预期工作。
答案 1 :(得分:8)
您正在通过编写operator++
来增加内部x++ ++
的返回值。这意味着如果该运算符的返回值不是可修改的值,则代码将无法编译。
因此,如果您声明它返回Number
而不是Number &
,则无法修改它(函数的返回值是临时的而不是左值,除非它是引用,因此外部运算符++,它通过(非常量)引用获取它,不能将它绑定到由value返回的对象。
答案 2 :(得分:3)
你要做的事情很不寻常。后增量通常返回一个rvalue,表示对象之前增量(与预增量相反,后者首先递增对象,然后返回该对象本身,作为左值)。由于无法解释的原因,你基本上试图使后增量的行为与预增量相同。
通常,你会这样做:
class Number {
int n;
public:
// Pre-increment
Number& operator++() {
++n;
return *this;
}
Number operator++(int) {
Number temp = *this; // capture old value
++(*this);
return temp;
}
};
使用这个定义,x++++
不会编译 - 但是当x
是int
时它也不会编译:它实际上没有多大意义。
无论如何,它不适合你的原因如下。 x++++
被解释为
operator++(operator++(x, 0), 0)
内部operator++
调用返回临时Number
对象。外部operator++()
需要类型为Number&
的参数 - 但非const引用不能绑定到临时引用。当您更改声明以便operator++
返回Number&
- 左值 - 时,此返回值可以愉快地传递到外部operator++
调用。
答案 3 :(得分:0)
让我们首先观察你不能为int
链接这样的postincrement运算符!
然后在我遇到问题之前,让我建议不要写这样的非直观的代码。从现在开始,有人必须在一年后阅读您的课程,并希望尽可能轻松地学习。
考虑x++++
实际上类似于operator++(operator++(x, int), int)
所以现在发生的事情是第一个operator++
按值返回(导致返回未命名的临时值)。这个未命名的临时值不能绑定到第二个(外部)调用的非const引用参数,并且方法查找失败。
最后请注意,您的实现实际上并没有实现postfix增量:它实现了前缀增量。您应该删除int
参数(表示postfix)或修复实现以返回未修改的值。