英文:
Pointer to the same instance used in a different class
问题
在这个测试中,值是不同的,不是同一个实例,我想在*From `test()`*中得到55的结果。怎么做到这一点?
英文:
How to solve this situation: I have three classes, to call them A
, B
and C
. In C
I have members of A
and B
. How do I set a pointer in B
to have the same instance from C
to A
?
#include <stdio.h>
class A {
public:
int x; // no init, random to can test
A() {
printf("From A, x=%d\n", x);
}
void getP(A *ptr) {
ptr = this;
}
};
class B {
public:
A *a;
B() {
a->getP(a);
printf("From B, x=%d\n", a->x);
}
void test() {
printf("From test(), x=%d\n", a->x);
}
};
class C {
public:
A a; B b;
C() {
a.x=55;
printf("From C, x=%d\n", a.x);
b.test();
}
};
int main () {
C c;
return 0;
}
In this test, the values are different, is not the same instance, I want to have 55 result in From test()
. How to make this?
答案1
得分: 3
**代码中的问题:**
您当前的代码在`B`构造函数的这一行存在未定义行为([undefined behavior][1]):
a->getP(a);
这是因为在这一点上`a`尚未初始化,因此使用`->`对其进行解引用是未定义行为。
此外,`A::getP(A *ptr)`通过值获取`ptr`,因此它不会更新来自调用者的指针。
为了实现这一点,您需要通过引用获取它(`void getP(A * & ptr)`)。但实际上,这不再需要 - 请看下文。
**解决方案:**
为了实现您想要的效果,您可以在`B`的构造函数中添加一个`A*`参数,用于初始化`B::a`成员。
然后,在从`C`的构造函数中构造`B`时,传递`C::a`成员的地址。
现在不再需要`A::getP`。
以下是您的完整示例,带有这些修改。
(修改部分用“VVVVV”标记)。
#include <stdio.h>
class A {
public:
int x{ 0 };
A() {
printf("来自A,x=%d\n", x);
}
};
class B {
public:
A* a;
//----VVVVVV----VVVV---
B(A * a_) : a(a_) {
printf("来自B,x=%d\n", a->x);
}
void test() {
printf("从test(),x=%d\n", a->x);
}
};
class C {
public:
A a; B b;
//--------VVVVV--
C() : b(&a) {
a.x = 55;
printf("来自C,x=%d\n", a.x);
b.test();
}
};
int main() {
C c;
return 0;
}
输出:
来自A,x=0
来自B,x=0
来自C,x=55
从test(),x=55
请注意,有未初始化的数据是不好的实践,因此我将`A::x`初始化为0。
[1]:https://en.wikipedia.org/wiki/Undefined_behavior
英文:
Issues in you code:
Your current code has UB (undefined behavior) in this line in B
constructor:
a->getP(a);
This is because a
is not initialized at this point and therefore it is UB to dereference it (with ->
).
In addition, A::getP(A *ptr)
is getting ptr
by value, and therefore it does not update the pointer from the caller.
In order to do so you need to get it by reference (void getP(A * & ptr)
). However it is not needed at all - see below.
Solution:
In order to achieve what you want, you can add a A*
parameter to the constructor of B
, that will be used to initialized B::a
member.
Then pass the address of C::a
member, when B
is constructed from C
's constructor.
There is also no need for A::getP
anymore.
Below is your complete example with this modification.
(the changes are marked with "VVVV").
#include <stdio.h>
class A {
public:
int x{ 0 };
A() {
printf("From A, x=%d\n", x);
}
};
class B {
public:
A* a;
//----VVVVVV----VVVV---
B(A * a_) : a(a_) {
printf("From B, x=%d\n", a->x);
}
void test() {
printf("From test(), x=%d\n", a->x);
}
};
class C {
public:
A a; B b;
//--------VVVVV--
C() : b(&a) {
a.x = 55;
printf("From C, x=%d\n", a.x);
b.test();
}
};
int main() {
C c;
return 0;
}
Output:
From A, x=0
From B, x=0
From C, x=55
From test(), x=55
Note that it's not a good practice to have uninitialized data, and therefore I initialized A::x
to 0.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论