C++ 类持有并返回指向另一个类的指针

C++ Class holding and returning pointer to another class

本文关键字:另一个 指针 返回 C++      更新时间:2023-10-16

>我一直在试图弄清楚类如何存储和检索类指针。

从我导入的库中得到了一个有限状态机类。当我想更改状态时,我会这样做:

// 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);

这运作良好。我希望某些状态实例执行更多操作,包括保留和返回状态,因此我添加了以下内容:

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上运行的。


编辑1

因此,在我进行了@deviantfan建议的更改后,代码编译了,但是每当我到达

barState.setNextState(fooState); 

该程序存在某种内存问题,并跳转到程序的另一个随机部分,然后崩溃。这应该只是调用:

void setNextState(const State &state) {*followingState = state;} 

所以我不确定为什么我的程序会发疯。但很可能不是,我在其他地方对数组和/指针做了一些粗心大意的事情。


编辑2

我找到了一些问题的原因(将"\0"写入一个非常错误的地址),但是当我尝试使用从getFollowState返回的对象地址时,它仍然崩溃。我现在拥有的:

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.

此行可能没有执行您的预期:

void setNextState(const State &state) {*followingState = state;} 

当你写*followingState时,你正在取消引用指针。这意味着它访问的是指向的对象,而不是指针本身。因此,该函数不会复制state的地址。相反,它试图制作其内容的全新副本,并将其放入followingState指向的任何内容中。

这是一个问题,因为它看起来followingState实际上并没有指向任何东西 - 它可能是一个空或野生(无效)指针。这意味着您的函数最终将数据复制到内存中的某个任意位置,从而导致未定义的行为。

相反,您希望复制state地址而不是其内容,如下所示:

void setNextState(const State &state) { followingState = &state; }

但是,为了做到这一点,您需要将followingState声明更改为 const State * followingState; .在这种情况下,const意味着指针可以重新分配给其他对象,但无法修改所指向的对象。

如果您希望能够修改状态,则需要从setNextState()参数列表中删除const