我一直想弄清楚Class如何存储和检索Class指针。(?)
我从导入的库中获得了一个有限状态机类。当我想改变状态时,我这样做:
// Set up my State instance
void fooEntry();
void fooUpdate();
void fooExit();
// Instantiate State object
State fooState(fooEntry,fooUpdate,fooExit);
// Instantiate FSM object
FiniteStateMachine stateMachine = FiniteStateMachine(fooState);
// Transition to this State
statemachine.transitionTo(fooState);
这很好用。我希望某些State实例做更多的事情,包括hold和return a State,所以我补充说:
class MyState: public State {
public:
MyState(void (*enterFunction)(), void (*updateFunction)(), void (*exitFunction)());
// Save a State's address to a State pointer
void setNextState(const State &state) {*followingState = state;}
State * nextState() { return followingState;} // Return pointer?
// Lot's more not pertinent to this question.
private:
State * followingState;
};
我希望能够做到这一点:
// Set up and instantiate my MyState instance
void barEntry();
void barUpdate();
void barExit();
MyState barState(barEntry(),barUpdate(),barExit());
barState.setNextState(fooState); // Pass it the next State I want to go to
// then later...
statemachine.transitionTo(barState.nextState()); // retrieve the State.
当我尝试编译时,我收到如下错误:
error: no matching function for call to 'FiniteStateMachine::transitionTo(State*)'
note: candidates are: FiniteStateMachine& FiniteStateMachine::transitionTo(State&)
这是从我致电statemachine.transitionTo(barState.nextState);
的时候起我已经尝试了&的所有组合和*我可以想到让它编译(更少的工作),直到我猜测。我希望有人能指出我的错误,也许会向我解释。
我不确定这是否重要,因为我只是在教自己C / C ++(20年太晚了),但这是在arduino上运行。
所以在我做了@deviantfan建议的更改后,编译了代码,但每当我到达
barState.setNextState(fooState);
该程序存在某种内存问题,并跳转到程序的另一个随机部分,然后崩溃。这应该只是呼唤:
void setNextState(const State &state) {*followingState = state;}
所以我不确定为什么我的程序会变得疯狂。但事实并非如此,我已经在其他地方对数组和/指针进行了粗心的处理。
我发现了一些问题的原因(写了一个非常错误的地址),但是当我尝试使用getFollowingState返回的对象地址时,它仍然崩溃了。我现在拥有的:
class MyState: public State {
public:
MyState(void (*enterFunction)(), void (*updateFunction)(), void (*exitFunction)());
// Save a State's address to a State pointer
void setFollowingState(State &state) {followingState = &state;} // followingState should be a pointer to a State object.
State * getFollowingState() { return followingState;} // Return pointer?
// Lot's more not pertinent to this question.
private:
State * followingState; // a pointer to a state object.
};
要使用它,我会这样做:
// Set up and instantiate my MyState instance
void barEntry(); void barUpdate(); void barExit();
MyState barState(barEntry(),barUpdate(),barExit());
barState.setFollowingState(fooState); // Pass it the next State I want to go to
statemachine.transitionTo(barState);
// then later within one of fooState's functions,
statemachine.transitionTo(*barState.getFollowingtState()); // retrieve the State.
答案 0 :(得分:2)
这条线可能没有达到你的期望:
void setNextState(const State &state) {*followingState = state;}
当您编写*followingState
时,您将取消引用指针。这意味着它访问了指向的对象,而不是指针本身。因此,该功能不会复制state
的地址。相反,它试图制作其内容的全新副本,并将其放入followingState
指向的任何内容中。
这是一个问题,因为看起来followingState
实际上并没有指向任何东西 - 它可能是一个空的或狂野的(无效的)指针。这意味着您的函数最终会将数据复制到内存中的某个任意位置,从而导致未定义的行为。
相反,您要复制state
的地址而不是其内容,如下所示:
void setNextState(const State &state) { followingState = &state; }
为了做到这一点,您需要将followingState
的声明更改为const State * followingState;
。在这种情况下,const
表示指针可以重新分配给不同的对象,但指向的对象不能被修改。
如果您希望能够修改状态,则需要从const
参数列表中删除setNextState()
。