同一对象的链接方法

时间:2017-10-18 01:20:16

标签: c++ chaining

我现在正在上课

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

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

2 个答案:

答案 0 :(得分:3)

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

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

答案 1 :(得分:2)

您的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)。
  6. 为了使用您希望使用的链接,您的所有操作都应该在相同的对象上进行,并且要实现您应该通过非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();
    }
    

    使用已删除的复制构造函数,此代码编译正常,因为没有副本发生。