1

単純なゲームの流れを管理するためのモデルとして、有限状態マシンを使用して実験しています。メインメニュー状態に入り、そこからゲームの開始やオプションの変更などを選択します。

私がそれを行っている方法は、各状態が継承する基本のStateクラスを作成することです。プログラムループを管理し、現在の状態へのポインターを追加するアプリケーションクラスがあります。アプリケーション自体には、現在の状態を終了して次の状態に入るchangeStateメソッドがあります。状態に入るとき、私はその状態にアプリケーションクラスへのポインタを与え、各状態は次の状態に切り替えるためのロジックを保持します。

これにより、何が起こっているのか、あるいは何が起こるべきかわからない状況が発生します。

特に:プログラムはイベントをポーリングします。イベントは処理のために現在の状態に渡されます。入力が次の状態への切り替えを指示する場合、changeState関数を呼び出します。状態変更機能は、現在の状態を削除し、次の状態をロードします。

混乱しているのは、状態変更関数を呼び出した状態を削除すると、状態変更関数から戻ったときに何が起こるかということです。私が何を意味するのかをより明確に示すための少し簡略化されたコード:

class Application
{
    public:
        void run();
        void changeState( StateBase * nextState );

    protected:
        void Initialize(){m_running=false; changeState(new BaseState);};

    private:
        StateBase * m_currentState;
        bool m_running;
};

void Application::run()
{
    Initialize();
    while (m_running)
    {
        Event event;
        while ( pollEvent(event) ) // Process events until event queue is empty
        {
            m_currentState->handleEvent( event );
        }
    }
}

void Application::changeState( StateBase * nextState )
{
    if (m_currentState!= 0)
    {
        m_currentState->exit();
        delete m_currentState;
    }
    m_currentState = nextState;
    m_currentState->enter( this );
}

class StateBase()
{
    public:
        void enter(  Application * app ){ m_Application = app };
        void handleEvent( Event const& event );
        void exit(){};
    private:
        Application * m_Application;
}

void StateBase::handleEvent( Event const& event )
{
    if ( event )
        m_Application->changeState( new StateBase );
}

int main()
{
    Application App;
    App.run();
    return 0;
}

そこに重要な部分だけを入れようとしました。とにかく、そのとき私が見ているのは、アプリケーションをインスタンス化することです。次に、public run()メソッドを呼び出します。このメソッドは、Initialize()を呼び出してm_running変数をtrueに設定し、changeStateを新しいBaseStateに呼び出します。changeStateは、状態にこれへのポインターを与えるため、イベントはアプリケーションの情報にアクセスできます。

次に、runメソッドはイベントをポーリングし、イベントを検出すると、処理のために現在の状態に送信します。

イベントが状態の変化を要求する場合、m_Application-> changeState(new StateBase);を呼び出します。

そして、ここが私が混乱しているところです。changeState()は、呼び出しを行うStateBaseのインスタンスであるm_currentStateでdeleteを呼び出します。コントロールがchangeState()から戻ると、削除されるべきイベントに移動します。しかし、私はそれをテストしました、そしてそれはクラッシュしません。もちろん、私はどの州のメンバーも変更しようとはしませんでした。

とにかく、ここで何が起こっているのか誰かが私に説明できるかどうか知りたいです。アプリケーションやさまざまな状態にシングルトンを使用するなど、これを管理するためのより良い方法を模索しています。これにより、ポインターを渡したり、状態を削除したりする必要がなくなります。しかし、この特定の結び目が私の注意を引きました。

4

1 に答える 1

1

次の状態に変更した後、指定された状態で何もしようとしなかった場合、何も問題は発生しません。要するに、それはメンバー関数からの削除と呼ばれるようなものです-これがオブジェクトに起こる最後のことである場合に許可されます:

void Test::deleteMe(int c)
{
   extern int b;
   int a;
   void f();
   delete this;
   // do not do this - do not touch/use this after delete
   // this->a = 7; 
   // this->f(); 
   // but you can use outer world and local variables
   a = 7;
   b = 8;
   c = 9;
   f(); 
   return; // just returns from function after delete this.
}

(C ++の世界とは反対に)理解しやすいCの世界では、同等のものは次のとおりです。

Test* this;
....
void Test_deleteMe(Test* this)
{
   free(this);
   // this->a = 7; // do not do this
   // f(this); // and this 
   return; // just returns from function after delete this.
} 
于 2012-10-20T23:21:41.347 に答える