Вложенный конечный автомат C ++ - PullRequest
0 голосов
/ 20 апреля 2020

впервые в Stackoverflow! Я довольно новичок в C ++ и OOP, и в настоящее время я борюсь с проблемой при попытке создать StateChart в C ++.

Я нашел некоторую документацию, объясняющую, как создать конечный автомат с n-состояниями и Пример кода, имитирующего переходы Красный-Зеленый-Желтый в трафике c light.

Я сообщаю код ниже:

Заголовок

class TLState
{
  public:
     virtual void Handle() = 0;
};

class TLNetTraffic
{
    private:
        TLState* _state;
    public:
        TLNetTraffic();
        void setState ( TLState* state );
        void Handle();
};

class TLRed: public myTLState
{
    private:
        TLNetTraffic* _context;

    public:
        TLRed(TLNetTraffic* context);
        void Handle();
};

class TLGreen: public TLState
{
    private:
        TLNetTraffic* _context;

    public:
        TLGreen(TLNetTraffic* context);
        void Handle();
};

class TLYellow: public TLState
{
    private:
        TLNetTraffic* _context;

    public:
        TLYellow(TLNetTraffic* context);
        void Handle();
};

cpp

#include "classes.h"
#include <iostream>

TLNetTraffic::TLNetTraffic()
{
    _state = new TLRed(this);
}

void TLNetTraffic::setState ( TLState* state )
{
    _state = state;
}

void TLNetTraffic::Handle ()
{
    _state->Handle();
}

TLRed::TLRed(TLNetTraffic* context): _context(context) {}

void TLRed::Handle()
{
    std::cout << "Red Light" << std::endl;
    _context->setState( new TLGreen(_context) );
}

TLGreen::TLGreen(TLNetTraffic* context): _context(context) {}

void TLGreen::Handle()
{
    std::cout << "Green Light" << std::endl;
    _context->setState( new TLYellow(_context) );
}

TLYellow::TLYellow(TLNetTraffic* context): _context(context) {}

void TLYellow::Handle()
{
    std::cout << "Yellow Light" << std::endl;
    _context->setState( new TLRed(_context) );
}

Есть мой вопрос: я хотел бы расширить такой пример подсостояниями для каждого верхнего состояния, например Red_1, Red_2, Red_3 , Green_1, Green_2, Green_3, Yellow_1, Yellow_2, Yellow_3 ...

Теперь самое простое, что я имею в виду, это "рассмотреть" все состояния на одном уровне и использовать структуру, описанную выше. Лично мне не нравится это решение, и мне было интересно, можно ли реализовать более приятный дизайн. Я попытался изменить код следующим образом (я сообщаю только о «красном» классе):

class myTLState
{
  public:
     virtual void Handle() = 0;
};

class myTLState_internal //NEW VIRTUAL CLASS
{
  public:
     virtual void Handle() = 0;
};

class myTLNetTraffic
{
    private:
        myTLState* _state;
    public:
        myTLNetTraffic();
        void setState ( myTLState* state );
        void Handle();
};

class myTLRed: public myTLState
{
    private:
        myTLNetTraffic* _context;
        myTLState_internal* _internal_state; //NEW POINTER TO THE NEW VIRTUAL CLASS

    public:
        myTLRed(myTLNetTraffic* context);
        void Handle();
        void setState ( myTLState_internal* _internal_state );
};

class myTLRed_internal1: public myTLState_internal
{
    private:
        myTLRed* _internal_context;

    public:
        myTLRed_internal1(myTLRed* context);
        void Handle();
};

class myTLRed_internal2: public myTLState_internal
{
    private:
        myTLRed* _internal_context;

    public:
        myTLRed_internal2(myTLRed* context);
        void Handle();

};

Я добавил в cpp следующее:

myTLRed::myTLRed(myTLNetTraffic* context): _context(context)
{
         _internal_state = new myTLRed_internal1(this);
}

myTLRed_internal1::myTLRed_internal1(myTLRed* context): _internal_context(context){}

Я получаю следующее сообщение об ошибке: неопределенная ссылка на 'vtable for myTLRed_internal1'

Честно говоря, понятия не имею, что это такое, и является ли это правильным способом. Любая помощь могла бы быть полезна. Большое спасибо и извините за длинный пост.

РЕДАКТИРОВАТЬ для всех тех, кто указывает, что есть большая утечка памяти: вы совершенно правы, я знал об этом, но сообщил только код, как я его нашел ради простоты. Следующее улучшение во избежание утечки памяти - использование интеллектуальных указателей, это мой план.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...