2015-11-30 8 views
0

У меня есть машина состояний, такая как код, который имеет состояние A, B и C и функцию changeState (char i), которая может изменять состояние системы, и каждое состояние может вызывать changeState (char i) для переключения системы в другое состояние:Как сохранить последнее созданное состояние при рекурсивном изменении состояния в конечном автомате?

struct State{ 
    State(char aName){ 
     this->name=aName; 
    } 
    char name; 
}; 

void changeState(char i); 

struct A : public State{ 
    A():State('A'){ 
     changeState('B'); 
    } 
}; 

struct B : public State{ 
    B():State('B'){ 
     changeState('C'); 
    } 
}; 

struct C : public State{ 
    C():State('C'){ 
    } 
}; 

State* state; 
void changeState(char i){ 
    switch(i){ 
     case 'A': 
      state=new A(); 
      break; 
     case 'B': 
      state=new B(); 
      break; 
     case 'C': 
      state=new C(); 
      break; 
    } 
} 

Теперь я хочу, чтобы вызвать изменение состояния, начиная с А до с:

int main(){ 
    changeState('A'); 
    printf("%c\n",state->name); 
    return 0; 
} 

поток: changeState ('A') -> новый A() -> changeState ('B') -> new B() -> changeState (C) -> new C(), я хочу, чтобы последнее состояние было C, но теперь это A, как я могу изменить changeState (char i), чтобы сделать это ? Я пытаюсь использовать список, чтобы держать все временные состояния объекта:

std::list<State*> stateList; 
void changeState(char i){ 
    switch(i){ 
     case 'A': 
      stateList.push_front(new A()); 
      break; 
     case 'B': 
      stateList.push_front(new B()); 
      break; 
     case 'C': 
      stateList.push_front(new C()); 
      break; 
    } 
    stateList.pop_back(); 
} 

int main(){ 
    stateList.push_front(new State('s')); 
    changeState('A'); 
    printf("%lu %c\n",stateList.size(),stateList.back()->name); 
    return 0; 
} 

но последнее состояние по-прежнему А вместо С, как я могу изменить changeState (символ I)?

+2

На несвязанной ноте я надеюсь, что это не ваш фактический код, или у вас будет много утечек памяти. –

ответ

0

Позволяет разбить первоначальный вызов, используя changeState('A') в операции, что происходит:

  1. Вы называете `changeState ('A')
  2. Вы делаете new A()
  3. который вызывает A конструктор, который вызывает changeState('B')
  4. new B()
  5. B звонок строителя changeState('C')
  6. Что делает new C()
  7. И новый объект C присваивается указатель state
  8. changeState возвращается, возвращаясь к B конструктор
  9. The B конструктор возвращает, что ставит управление обратно в changeState('B') вызова
  10. Выполнение задания state = new B()
  11. changeState функция return ы к A конструктор
  12. The A конструктор возвращается к changeState('A') вызова
  13. state = new A() назначение производится
  14. changeState функция возвращает в функцию main
  15. Переменная state теперь указывает на A объекта

Простейшее решение? Не вызывайте changeState в конструкторах!


Как и в случае с другим примером со списком, помните, что список начинается пустым. Затем, когда вы вызываете changeState, вы добавляете узел, а затем сразу удаляете тот же узел, который вы только что добавили.

 Смежные вопросы

  • Нет связанных вопросов^_^