同一对象的链接方法
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,你会得到正确的结果。
您的 incrementX
和 incrementY
按值运行 return。也就是说,从这些函数中 return 复制您的对象,因此后续操作发生在 不同的实例 。
如果删除复制构造函数,您可能会看到编译发生错误。为此添加
Point(const Point&) = delete;
(假设 c++11 或更高版本使用 delete
。如果旧的只是将其设为私有)
因此要诊断您的实际错误:
- 您使用值 (2, 3) 构造
Point
。
- 对
incrementX
的第一次调用在您的原始实例上运行(现在值为 (3,3))并在 [=65= 上传递一个副本].
incrementY
对临时副本进行操作并将其值更新为 (3, 4)。它也是 return 的副本。
- 您打印了第二个临时副本,得到了预期的结果 (3,4)。
- 现在
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();
}
使用删除的复制构造函数,这段代码可以正常编译,因为没有复制发生。
我现在正在 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,你会得到正确的结果。
您的 incrementX
和 incrementY
按值运行 return。也就是说,从这些函数中 return 复制您的对象,因此后续操作发生在 不同的实例 。
如果删除复制构造函数,您可能会看到编译发生错误。为此添加
Point(const Point&) = delete;
(假设 c++11 或更高版本使用 delete
。如果旧的只是将其设为私有)
因此要诊断您的实际错误:
- 您使用值 (2, 3) 构造
Point
。 - 对
incrementX
的第一次调用在您的原始实例上运行(现在值为 (3,3))并在 [=65= 上传递一个副本]. incrementY
对临时副本进行操作并将其值更新为 (3, 4)。它也是 return 的副本。- 您打印了第二个临时副本,得到了预期的结果 (3,4)。
- 现在
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();
}
使用删除的复制构造函数,这段代码可以正常编译,因为没有复制发生。