同一对象的链接方法

chaining method of same object

本文关键字:链接 方法 对象      更新时间:2023-10-16

我现在正在上课

但是存在调用方法链的问题(这里是代码

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)是实际类打印的......

a.incrementX()递增成员值。a.incrementX().incrementY()增加临时实例化并被丢弃。

Point Point::incrementX()函数中将点替换为Point&,您将获得正确的结果。

您的incrementXincrementY函数按值返回。也就是说,从这些函数返回后,您的对象将被复制,因此后续操作发生在不同的实例上。

如果您删除复制构造函数,您可能会看到编译中发生错误。为此,请添加

Point(const Point&) = delete;

(假设 C++11 或更高版本使用delete。如果较旧,只需将其设为私有)

因此,要诊断您的实际错误:

  1. 使用值(2, 3)构造Point
  2. incrementX的第一次调用在您的原始实例(现在的值为(3,3))上运行,并在返回时传递副本。
  3. incrementY对临时副本进行操作,并将其值更新为 (3, 4)。它还返回一个副本。
  4. 打印具有预期结果 (3,4) 的第二个临时副本。
  5. 现在a.print()显示您的原始Point,该自调用incrementX以来未被触摸过,并显示 (3,3)。

为了使用您希望使用的链接,所有操作都应在同一对象上进行,并且为了实现这一点,您应该通过非常量引用从这些函数返回。

函数签名

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();
}

使用已删除的复制构造函数,此代码可以很好地编译,因为没有发生任何副本。