我有一个A类,它包含几个实例变量和一个B类,它接受对该类的引用并更改实例变量。在B类更改这些变量之后,您会认为这些变量会在类的原始实例中更改,但在这种情况下它们不会。为什么会发生这种情况?我该如何解决这个问题?
class Foo {
public:
int x;
int y;
Foo() {
}
Foo(int x, int y) {
this->x = x;
this->y = y;
}
};
class Bar {
public:
Foo foo;
Bar() {
}
Bar(Foo& foo) {
this->foo = foo;
}
void Swap() {
int tmp = foo.x;
foo.x = foo.y;
foo.y = tmp;
}
};
int main()
{
Foo foo(4, 8);
Bar bar(foo);
std::cout << "this is x: " << foo.x << std::endl; //prints 4
std::cout << "this is y: " << foo.y << std::endl; //prints 8
bar.Swap();
std::cout << "this is x: " << foo.x << std::endl; //prints 4, but should print 8
std::cout << "this is y: " << foo.y << std::endl; //prints 8, but should print 4
}
答案 0 :(得分:3)
类B
的构造函数确实通过引用获取foo
(参数),但会立即将其复制到A
的单独实例中(特别是foo
}成员); Swap
然后在foo
成员上工作,如上所述,该成员只是原始对象的副本。
要使代码按预期运行,您必须使成员foo
成为引用(或指针):
class Bar {
public:
Foo &foo;
Bar() {
}
Bar(Foo& foo) : foo(foo) {
}
(请注意我必须使用the member initialization list syntax因为引用cannot be default-initialized and then reseated)
答案 1 :(得分:0)
您将对foo的引用传递给bar的构造函数,但随后通过引用bar.foo分配(复制)您传递的foo。
您希望将其声明为对Foo对象(或指针)的引用,而不是单独的Foo对象。
答案 2 :(得分:0)
问题出在这里。
Foo foo;
Bar(Foo& foo) {
this->foo = foo;
}
即使您通过引用获取foo
参数,也可以将其分配给非参考值,从而生成副本并解决您提出的问题。解决方案的第一步是通过引用声明您的实例字段。
Foo& foo;
但是当您尝试分配给它时会导致错误。为此,我们希望使用特殊的构造函数初始化语法。它与赋值基本相同,但执行构造而不是正常赋值。所以编写你的构造函数如下。
Bar(Foo& foo) : foo(foo) {}
您还必须完全删除默认构造函数Bar()
,因为大多数C ++编译器会拒绝可能导致未初始化引用的代码。