proudmore
@proudmore

Как организовать структуру классов?

Здравствуйте.
code

Вот у меня есть суперкласс:
class Strategy
{
    public:
        virtual void execute();
        void save(){
            EEPROM.put(source.getEepromPosition(), this);
        }

        Strategy get(bool pos){
            return EEPROM.get(pos ? 0 : 512, Strategy);
        }

    protected:
        ControlButton source;
};

И наследники:

DuplicateStrategy:
#include <Arduino.h>

class DuplicateStrategy : public Strategy
{
    public:
        DuplicateStrategy(Button target, ControlButton controlButton){
            this->target = target;
            this->source = controlButton;
            this->save();
        }

        void execute(){
            this->source.hasCommand() ? this->target.push() : this->target.release();
        }

    private: 
        Button target;

};


MacroStrategy:
#include <Arduino.h>

class MacroStrategy : public Strategy
{
    public:
        MacroStrategy(ControlButton source, MacroPosition positions[]){
            this->source = source;
            this->positions = positions;
            this.save();
        }

        void execute(){
            if(source.hasCommand()){
                for(int i = 0; i < sizeof(this->positions); i++){
                    positions[i].execute();
                }
            }
        }

    private:
        MacroPosition positions[];
}


MultiClickStrategy:
#include <Arduino.h>

class MultiClickStrategy : public Strategy
{
    public:

        MultiClickStrategy(Button target, ControlButton source, unsigned int delay){
            this->target = target;
            this->source = source;
            this->delay_ms = delay;
            this.save();
        }

        void execute(){
            if(source.hasCommand() && this.timeSpent()){
                this->timer = millis();
                target.isPushed() ? target.release() : target.push();
            }
        }
    
    private:
        unsigned long timer;
        unsigned int delay_ms;
        Button target;

        bool timeSpent(){
            return millis() > this->timer + this->delay_ms;
        }
}


Вопрос вот в чем. Я хочу хранить наследников Strategy в массиве типа Strategy[], и у каждой Strategy иметь возможность вызвать execute().
Мне кажется, это, в принципе, реально и я правильно сделал, но есть одна тонкость. Я пишу прошивку для МК, и мне нужно сохранять в EEPROM (энергонезависимую память) сериализованные Strategy. Для этого есть методы:
Get
Put

Если бы я знал, какой именно класс лежит в EEPROM, то проблемы, скорей всего, не было бы, но т.к. я этого не знаю, то стоит вопрос, как быть. Предполагаю, что можно попробовать вторым параметром метода Get указать Strategy, но VS говорит, что так нельзя.

В общем, прошу помощи.
  • Вопрос задан
  • 117 просмотров
Пригласить эксперта
Ответы на вопрос 1
@Mercury13
Программист на «си с крестами» и не только
Strategy[N] хранит не наследников Strategy, а объекты класса Strategy. Поэтому в массиве придётся хранить не тела объектов, а указатели.

Если у вашего МК есть полноценное управление памятью с операцией new, всё просто: std::unique_ptr<Strategy> strategies[N]. Если нет — приходится как-то извращаться, и об этом не будем.

Как сериализировать? Добавим классу Strategy небольшую функцию
unsigned char code() const;
Пусть первая стратегия возвращает, например, 1=CODE_DUPLICATE, а вторая — 2=CODE_MACRO. Сериализация, в числе прочего, будет записывать в память эти коды.

Считав код, мы создаём Duplicate или Macro, а затем считываем объект этого класса.
std::unique_ptr<Strategy>& thatObject = strategies[i];
switch (getSomeByte) {
case CODE_DUPLICATE:
  thatObject = new DuplicateStrategy();
  break;
case CODE_MACRO:
  thatObject = new MacroStrategy();
  break;
default:
  // можно ничего не делать. Можно сообщить об ошибке.
}
thatObject->read();
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы