我现在正在上课
但是调用方法链存在问题(这里是代码
class Point{
public:
int x;
int y;
Point(int i , int j);
Point incrementX();
Point incrementY();
void print();
};
Point::Point(int i, int j){
x = i;
y = j;
}
Point Point::incrementX(){
x++;
return(*this);
}
Point Point::incrementY(){
y++;
return(*this);
}
void Point::print(){
cout << "(" << x << "," << y << ")" << endl;
}
void Q11(){
Point a(2,3);
//(3,4)
a.incrementX().incrementY().print();
//(3,3)why 33 here ??
a.print();
}
我很困惑为什么最后一个代码a.print()
会给出(3,3)
我尝试在方法
中打印出this
的地址
我在调用incrementX()
和incrementY()
不同时找到了这两个地址
我的猜测是incrementX()
访问该类,但在调用incrementY()
时,该类被占用。所以它在堆中创建了一个类的副本,然后incrementY()
更改了副本中的y ...
所以(3,4)
是按副本打印的,(3,3)
是按实际班级打印的......
答案 0 :(得分:3)
仅a.incrementX()
增加成员值。 a.incrementX().incrementY()
增加临时实例化并被丢弃。
用Point&
函数中的Point Point::incrementX()
替换Point,您将得到正确的结果。
答案 1 :(得分:2)
您的incrementX
和incrementY
函数按值返回。也就是说,从这些函数返回后,您的对象将被复制,因此后续操作将在不同的实例上进行。
如果要删除复制构造函数,您可能会在编译中看到错误。为此,添加
Point(const Point&) = delete;
(假设c ++ 11或更高版本使用delete
。如果年龄较大,则将其设为私有)
所以要诊断你的实际错误:
Point
。 incrementX
的第一次调用对您的原始实例(现在为值(3,3))进行操作,并在返回时传递一份副本。 incrementY
对临时副本进行操作,并将其值更新为(3,4)。它还会返回一份副本。a.print()
显示自调用Point
以来未触及的原始incrementX
,并显示(3,3)。为了使用您希望使用的链接,您的所有操作都应该在相同的对象上进行,并且要实现您应该通过非const 从这些函数返回参考强>
功能签名
Point Point::incrementX()
变为
Point& Point::incrementX()
,完整的代码看起来像。
#include <iostream>
using namespace std;
class Point{
public:
int x;
int y;
Point(int i , int j);
//Point(const Point&) = delete;
Point& incrementX();
Point& incrementY();
void print();
};
Point::Point(int i, int j){
x = i;
y = j;
}
Point& Point::incrementX(){
x++;
return(*this);
}
Point& Point::incrementY(){
y++;
return(*this);
}
void Point::print(){
cout << "(" << x << "," << y << ")" << endl;
}
int main(){
Point a(2,3);
a.incrementX().incrementY().print();
a.print();
}
使用已删除的复制构造函数,此代码编译正常,因为没有副本发生。