#c
#c
Вопрос:
Я пытаюсь создать какую-то таблицу переходов для StateMachine. Я довольно новичок в шаблонах. Поэтому, пожалуйста, простите меня, если я допустил глупую ошибку.
Это мой код для класса Transitiontable: .cpp и .h
template<typename T, typename ...Arg>
class TransitionTable
{
public:
TransitionTable(T first, Arg... rest);
~TransitionTable();
};
template <typename T, typename ... Arg>
TransitionTable<T, Arg...>::TransitionTable(T first, Arg... rest) {
std::cout << "New Transition Table" << std::endl;
std::unique_ptr<T> Test = new T;
TransitionTable(rest...);
}
template <typename T, typename ... Arg>
TransitionTable<T, Arg...>::~TransitionTable() {}
Это мой основной ():
int main() {
TransitionTable
<
State1, State2, Event1,
State1, State3, Event2,
State2, State3, Event1,
State2, State1, Event2,
State3, State1, Event1,
State3, State2, Event2
> test(State1, State2, Event1,
State1, State3, Event2,
State2, State3, Event1,
State2, State1, Event2,
State3, State1, Event1,
State3, State2, Event2);
return 0;
}
Итак, я пытаюсь создать новое состояние и сразу же после этого удалить новое состояние с помощью этого уникального указателя. Это просто для того, чтобы я попытался больше понять о шаблонах переменных. Все классы состояний Con и Destruktor имеют внутри себя cout, в котором указывается, создали ли они сами себя или удалили.
Пример для класса состояний. Все они выглядят одинаково:
public:
State1(){
std::cout << "State1 erstellt! " << m_Name << "n";
}
virtual ~State1() {
std::cout << "State1 zerstoert! " << m_Name << "n";
}
void Entry() override {
std::cout << "Entry State1!n";
}
void Exit() override {
std::cout << "Exit State1!n";
}
private:
std::string m_Name;
};
Моя проблема сейчас в том, что он практически ничего не делает.. Может кто-нибудь сказать мне, пожалуйста, почему? Если я установлю точку останова в самом начале, отладчик даже не откроется.
Приветствую и благодарю за помощь!
Редактировать:
Statemachine .cpp
StateMachine::StateMachine(): m_InitState(m_CurrentState) {}
StateMachine::StateMachine(std::string na, trans_map trans, AbstractState* init): m_Name(na),
m_InitState(init),
m_TransitionTable(trans) {}
StateMachine::~StateMachine() = default;
void StateMachine::Start() {
m_CurrentState = m_InitState;
std::cout << "Zustandsmachine gestartet!n";
m_CurrentState->Entry();
}
void StateMachine::Stop() {
m_CurrentState->Exit();
m_CurrentState = nullptr;
std::cout << "Zustandsmachine gestoppt!n";
}
void StateMachine::HandleEvent(AbstractEvent* ev) {
for(auto outer_map : m_TransitionTable) {
if(outer_map.first == m_CurrentState) {
if(outer_map.second.find(ev)->second)
m_NextState = outer_map.second.find(ev)->second;
}
}
if (m_CurrentState != m_NextState)
Transition();
}
void StateMachine::Transition() {
m_CurrentState->Exit();
m_NextState->Entry();
m_CurrentState = m_NextState;
}
void StateMachine::SetInitState(AbstractState* init) {
m_InitState = init;
}
void StateMachine::CreateTransitionTable(const trans_mapamp; transition) {
m_TransitionTable = transition;
}
AbstractState* StateMachine::GetCurrentState() const {
return m_CurrentState;
}
Statemachine .h
#pragma once
#include <map>
#include <string>
#include <iostream>
#include "AbstractState.h"
#include "AbstractEvent.h"
typedef std::map<AbstractEvent*, AbstractState* > trans_map_inner;
typedef std::map<AbstractState*, trans_map_inner> trans_map;
class StateMachine{
public:
StateMachine();
StateMachine(std::string na, trans_map trans, AbstractState* init);
~StateMachine();
void Start();
void Stop();
void HandleEvent(AbstractEvent* ev);
void Transition();
void SetInitState(AbstractState* init);
void CreateTransitionTable(const trans_mapamp; transition);
AbstractState* GetCurrentState() const;
private:
std::string m_Name;
AbstractState* m_CurrentState = nullptr;
AbstractState* m_NextState = nullptr;
AbstractState* m_InitState;
trans_map m_TransitionTable;
};
Классы Abstractstate и Abstactevent — это всего лишь небольшие абстрактные классы.
Комментарии:
1. c ??. Вы имеете в виду под: «Это мой код для класса Transitiontable: .cpp и .h». Поскольку это шаблонный класс, весь код должен быть доступен в callsite -> only header. Если я правильно помню,
TransitionTable
в теле вашего конструктора это сокращение отTransitionTable<T,Arg...>
, поэтому я бы ожидал некоторого количества ошибок параметров. Но поскольку вы не упомянули что-то подобное, я, должно быть, ошибаюсь.2. Вы уверены, что выполняете отладочную сборку? Какую IDE / компилятор вы используете?
3. Я думаю, вы правы. Я помню что-то вроде того, что все должно быть в заголовке, но это не решило мою проблему… Я использую VS 2015 Pro. Компилятор, я полагаю, g ? Но я не уверен. Да, я уверен, что запускаю отладку.
4. @HenningWilmer Нет, если вы используете,
Visual Studio
ваш компилятор являетсяVC
компилятором5. @WBuck Спасибо! Полезно знать.
Ответ №1:
Проблема в том, что это
TransitionTable
<
State1, State2, Event1,
State1, State3, Event2,
State2, State3, Event1,
State2, State1, Event2,
State3, State1, Event1,
State3, State2, Event2
> test(State1, State2, Event1,
State1, State3, Event2,
State2, State3, Event1,
State2, State1, Event2,
State3, State1, Event1,
State3, State2, Event2);
не вызывает конструктор, как вы можете подумать. То, что вы написали там, является объявлением функции, которая возвращает TransitionTable<State1, State2, …>
и принимает параметры типов State1, State2, …
. Итак, ваш код действительно ничего не делает, кроме объявления функции и возврата 0. Это также известно как самый неприятный синтаксический анализ. Если бы вы хотели, чтобы это был вызов конструктора, вам пришлось бы создавать объекты типов State1, State2, …
и предоставлять их в качестве аргументов конструктору. State1, State2, …
это не список аргументов вызова функции, это список типов…
Комментарии:
1. Большое вам спасибо. Это объясняет это. Моя проблема в том, что я не хочу создавать объекты. Я только хочу создать состояние, которое в данный момент активно, и уничтожить его, если оно покинет состояние.
2. @HenningWilmer Хорошо, но тогда почему вы
TransitionTable
ожидаете, что в качестве аргумента будет использоваться один объект любого типа состояния?3. Я бы сказал, потому что это неправильно. Мне нужна таблица переходов, которая принимает все классы состояний, и если мне нужно обработать событие, я хочу заглянуть в таблицу переходов и создать из нее новый объект Nextstate.
4. @HenningWilmer Ну, ваш
TranstitionTable
знает все типы состояний, поэтому он должен быть способен создавать объекты состояний по мере необходимости. Но для этого ему нужно будет каким-то образом знать, в каком состоянии он находится, и иметь информацию о том, из какого состояния переходить, где оно находится. Ваш вопрос, похоже, не указывает, как все это должно обрабатываться…5. У меня есть класс Statemachine, который обрабатывает все это. И переходы находятся внутри приведенного выше кода. Итак, если появляется его пример для State1 и Event1, он переключается в State2.. Но не могли бы вы объяснить мне, как извлечь типы состояний? И как Transitiontable узнает все состояния? Я