2012-10-20 86 views
1

我正在嘗試使用有限狀態機作爲管理簡單遊戲流程的模型。進入主菜單狀態,從中選擇開始遊戲或修改選項等。在FSM中切換狀態

我這樣做的方式是創建一個基本狀態類,每個狀態從其繼承。我有一個應用程序類來管理程序循環,並添加一個指向當前狀態的指針。應用程序本身有一個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給這個狀態一個指針,所以事件可以訪問應用程序的信息。

運行方法然後輪詢事件,當它檢測到一個時,它將它發送到當前狀態進行處理。

如果一個事件要求改變狀態,它會調用m_Application-> changeState(new StateBase);

這裏是我困惑的地方。 changeState()調用m_currentState上的刪除,這是StateBase發出呼叫的實例。當控制從changeState()返回時,它會轉到應該刪除的事件。但是,我測試了它並沒有崩潰。當然,我也沒有試圖修改任何州的成員。

無論如何,我想知道是否有人能向我解釋發生了什麼事。我仍然試圖找出一個更好的方法來管理這個問題,比如使用單例對應用程序和不同的狀態,這樣可以消除在我完成時處理指針和刪除狀態的需要。但是這個特別的結引起了我的注意。

回答

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. 
}