2013-10-30 109 views
2

我最近發表了一個問題,有人指出我會犯錯!如何安全地更改狀態對象之間的狀態?

main()我正在做一個狀態,然後將整數傳遞給processState()並基於整數它將改變狀態(通過銷燬狀態並創建一個新狀態的新實例),或保持不變州。

我指出的主要問題是函數void state_t::changeState(state_t * new_state)。我刪除了「this」,然後指向已刪除的「_state」指針指向新的狀態......現在,我指出,這顯然是一件壞事。

所以問題是:使用不同狀態實現這種狀態切換的最佳方式是什麼?也許_state需要是一個全局指針指向當前狀態還是一些這樣的?

Main.cpp的:

#include <QCoreApplication> 
#include <QDebug> 
#include "statemachine.h" 

int main(int argc, char *argv[]) 
{ 
    QCoreApplication a(argc, argv); 

    state_t *myState = new testState1(); 

    myState = myState->processState(1); 
    myState = myState->processState(2); 
    myState = myState->processState(3); 
    myState = myState->processState(1); 

    return a.exec(); 
} 

基本類型:

#include "state_t.h" 

state_t::state_t(QByteArray stateName) : 
    name(stateName), 
    _state(this) 
{ 
    qDebug() << this->name << ": Creating state"; 
} 

state_t::~state_t() 
{ 
    qDebug() << this->name << ": Deleting state"; 
    qDebug() << endl; 
} 

void state_t::changeState(state_t * new_state) 
{ 
    // Check if the state has changed 
    if (this != new_state) 
    { 
     qDebug() << this->name << ": State changed to: " << new_state->name; 
     delete this; 
     _state = new_state; 
    } 
    else 
    { 
     qDebug() << this->name << ": State un-changed"; 
    } 
} 

void state_t::unknownStateEventHandler(int event) 
{ 
    qWarning() << this->name << ": Unknown event " << event; 
} 

State類(可以有很多這樣的):

#include "teststate1.h" 

testState1::testState1() : 
    state_t("state1") 
{ 
} 

state_t *testState1::processState(int event) 
{ 
    qDebug() << name << ": event" << event; 
    switch (event) 
    { 
     case 2: 
     { 
      changeState(new testState2()); 
      //changeState_t(testState2); 
      break; 
     } 
     default: 
     { 
      unknownStateEventHandler(event); 
      break; 
     } 
    } 

    return _state; 
} 
+0

@ScarletAmaranth:這是「所有的冰雹」。我們都會感激人們大喊大叫的時代結束了。 ;) – thokra

+0

@thokra這是一個不愉快的拼寫失敗,謝謝你,我剛剛刪除了評論:) – ScarletAmaranth

+0

@thokra&Scarlet ... lol :) –

回答

2

我認爲這個問題你」我們得到的結果是,你正在混合狀態機的行爲與狀態機的行爲;即執行狀態行爲與管理狀態更改。這些應該保持分開。

你可以有一個類來代表你的狀態機作爲一個整體。它沒有任何狀態特定的功能。相反,它將包含一個指向當前狀態對象的指針。 (我假設你的所有狀態類都是從一個公共基類派生的)。

當你想改變狀態時,狀態機類將刪除舊狀態並創建和/或存儲新狀態。各個狀態類不應該直接這樣做,儘管他們可以在狀態機上調用一個函數來啓動更改。

作爲一個方面說明,最好避免使用delete this。它在技術上可行,但通常不是一個好主意。

+1

實例自殺應該,如果有的話,應該非常謹慎。 – thokra

+0

謝謝,這是有道理的:) –

0

在你的情況,你不應該叫

`刪除;

_STATE = NEW_STATE;`

你應該只由NEW_STATE的值賦給這個:

*this = *new_state 

但我不認爲這是一個不錯的設計。請檢查這個example

+0

我看到你想說什麼,但在我的情況下,這並沒有達到目標,因爲我特別想刪除「舊/當前」狀態,然後實例化新的。鏈接是,但是非常有用:) –