问题描述
我尝试通过 cost1
类更改 C
字段,但是没有用。我如何通过 cost1
类访问和更改 M
(在 C
类中)。
我收到空指针错误,它显示在 setM
函数内。
class M {
protected:
int cost1;
public:
M() {}
M(int c1) :cost1(c1) {}
int getCost1() { return cost1; }
void setCost1(int c1) { cost1 = c1; }
};
class P {
protected:
M* _m;
public:
void setM(M m) {
_m = &m;
}
M getM() {
return *_m;
}
};
class C {
protected:
std::shared_ptr<P> _p;
M _m;
public:
C(M m) {
_m = m;
}
void setP(std::shared_ptr<P> p) {
_p = p;
}
void applyM() {
std::cout << _p->getM().getCost1() << std::endl;
_p->getM().setCost1(11);
std::cout << _p->getM().getCost1() << std::endl;
}
};
int main()
{
std::shared_ptr<P> p1;
M m1(5);
std::shared_ptr<C> c1 = std::make_shared<C>(m1);
p1->setM(m1);
c1->setP(p1);
c1->applyM();
}
解决方法
在下面的函数中
void setM(M m) {
_m = &m;
}
您正在按值传递 m
。这会生成传递变量的本地副本。然后你获取复制的(本地!)变量的地址,一旦函数完成,它就会被销毁。
您需要通过引用或指针传递。
,你的班级P
有问题。它的构造函数按值接受一个 M
对象。这意味着当它被调用时,调用者的 M
对象的临时副本被创建并传递给它。该临时地址随后存储在受保护成员 _m
中。构造函数执行完毕后,临时副本被销毁,_m
指针无效,访问它会导致未定义行为。
解决办法是传递你要存储的地址。
class P {
protected:
M* _m;
public:
void setM(M* p) {
_m = p;
}
M getM() {
return *_m;
}
};
main
中也有问题
std::shared_ptr<P> p1;
...
p1->setM(m1);
您在未初始化的情况下取消引用指针 p1
。同样,这将导致未定义行为。