Шаблон состояния - С++

Я пытаюсь реализовать конечный автомат с шаблоном проектирования состояний, я очень новичок в С++ и начинающий программист в целом. include и заголовочные файлы меня смущают, и я не совсем уверен, как правильно настроить этот проект. Я, вероятно, должен начать с чего-то другого, но у меня действительно нет выбора.

Цель машины — прочитать символ и, в зависимости от состояния, сделать что-то другое.

Это макет класса, о котором я думал:

Machine.h

class Machine{
   void setCurrentState(State s);
   State currentState;
}

State.h

class State{
   virtual void read(char c, Machine* m) = 0;
}

(Should i make a header file for each derived class?)

Initial.h

class Initial: public State{
   void read(char c, Machine* m){
      m->setCurrentState(new SomeState());
   }
}

Я пытался сделать это таким образом, но я не понимаю, что и где я должен включать. Я получаю, в зависимости от того, как я делаю это неправильно, ошибки от не определенного типа до неопределенной ссылки vtable. Может быть, вы, ребята, могли бы помочь мне настроить это правильно и получить ссылку на точку, я очень ценю это.


person mdshields    schedule 20.04.2015    source источник
comment
State currentState; должно быть State* currentState;.   -  person πάντα ῥεῖ    schedule 20.04.2015
comment
Как правило, используйте одну пару h/cpp для каждого класса и по умолчанию делайте все переменные закрытыми. Кроме того, если вам нужны указатели на другие классы, используйте std::shared_ptr или std::unique_ptr для автоматического управления ресурсами. Иногда вам также нужен std::weak_ptr.   -  person Erik Alapää    schedule 20.04.2015
comment
@ErikAlapää Обычно для State вам достаточно необработанных данных или std::weak_ptr, поскольку эти классы должны обеспечивать просто другое поведение, но не должны сами хранить данные.   -  person πάντα ῥεῖ    schedule 20.04.2015
comment
Да, weak_ptr также хорош для разрыва циклов, так что вы не получите утечек памяти.   -  person Erik Alapää    schedule 20.04.2015
comment
Также я думаю, стоит отметить, что это выглядит как классический ООП-подход. Может быть, проще начать с более функционального, а затем уже оттуда дорабатывать: using State = uint8_t; struct Result { char output; State state }; Result myStateMachine( State state, char input) { switch(state) { ... } ...}   -  person BitTickler    schedule 23.03.2020


Ответы (1)


Вы можете использовать охранников C. Это означает, что вы объявляете некоторую переменную в каждом заголовочном файле.

#ifndef STATE_H
#define STATE_H
your header
#endif

Теперь все, что находится между #ifndef и #endif, не будет включаться дважды, и ld не будет возвращать ошибку.

В каждый исходный файл вы просто включаете то, что нужно источнику.

person Irimitenkan    schedule 20.04.2015
comment
OP должен будет решить проблему циклических зависимостей, а также использовать предварительное объявление. - person πάντα ῥεῖ; 20.04.2015