同一对象的链接方法

chaining method of same object

我现在正在 class

但是调用方法链有问题(这里是代码

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()访问了class,但是调用incrementY()时class被占用了。所以它在堆中复制 class 然后 incrementY() 改变副本中的 y...

所以(3,4)是复制打印的,(3,3)是实际打印的class...

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

Point Point::incrementX()函数中用Point&替换Point,你会得到正确的结果。

您的 incrementXincrementY 按值运行 return。也就是说,从这些函数中 return 复制您的对象,因此后续操作发生在 不同的实例

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

Point(const Point&) = delete;

(假设 c++11 或更高版本使用 delete。如果旧的只是将其设为私有)

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

  1. 您使用值 (2, 3) 构造 Point
  2. incrementX 的第一次调用在您的原始实例上运行(现在值为 (3,3))并在 [=65= 上传递一个副本].
  3. incrementY 对临时副本进行操作并将其值更新为 (3, 4)。它也是 return 的副本。
  4. 您打印了第二个临时副本,得到了预期的结果 (3,4)。
  5. 现在 a.print() 显示您的原始 Point,自从调用 incrementX 并显示 (3,3)。

为了利用您希望使用的链接,您的所有操作都应该在 相同的 对象上进行,并且为了实现这一点,您应该 return 来自非常量 reference.

的那些函数

函数签名

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

使用删除的复制构造函数,这段代码可以正常编译,因为没有复制发生。