Задать вопрос
@iihaarr

Как это можно реализовать?

Я реализую передвижение транспорта в зависимости от его типа(наземный транспорт, морской и т.п.)
Есть базовый класс транспорта и несколько его наследников
class BaseTransport {
public:
...Какие-то методы...
virtual void Move() = 0;
protected:
поля
}
class GroundTransport : public BaseTransport {
GroundEnum state;
public:
...
void Move() override;
}
class SeaTransport : public BaseTransport {
SeaEnum state;
public:
...
void Move() override;
}
class AirTransport : public BaseTransport {
AirEnum state;
public:
...
void Move() override;
}
...

У каждого наследника есть свой отдельный enum class. Эти enumы - возможные состояния для каждого типа транспорта. Все виды транспорта двигаются по маршруту, заданному некоторому набору точек. Когда транспорт доходит до конца маршрута, то в зависимости от типа транспорта он останавливается, либо возвращается в начало маршрута(то есть выставляется состояние на возвращение в начальную точку).
У наследников в методе Move есть одинаковый код, который отличается только значениями enum
void GroundTransport::Move() {
...одинаковый код...
state = GroundEnum::Finished
...одинаковый код...
}
void SeaTransport::Move() {
...одинаковый код...
state = SeaEnum::ReturnToBegin
...одинаковый код...
}
...

Как это можно свести к одному методу в базовом классе?
upd: Изменил описание вопроса
  • Вопрос задан
  • 154 просмотра
Подписаться 1 Средний 3 комментария
Пригласить эксперта
Ответы на вопрос 4
@rPman
Так чем не нравится шаблон?

окей, создай промежуточную функцию, где определи весь свой код со значением твоего enum в параметрах, можно даже пометить ее inline чтобы наверняка, если не доверяешь автоматической оптимизации

temlate <typename Derived1Enum> inline void Derived1::_someMethod(const Derived1Enum _state) {
...одинаковый код...
state = _state
...одинаковый код...
}
void Derived1::someMethod() {
_someMethod(Derived1Enum::SomeStateDerived1)
}
void Derived2::someMethod() {
_someMethod(Derived2Enum::SomeStateDerived2)
}

upd. подправил с использованием шаблона
Ответ написан
@dima20155
you don't choose c++. It chooses you
Самый банальный ответ: объединить enum
Также можно сделать базовый класс шаблонным, а наследоваться уже от базового класса со специализированным шаблоном
Если это единственное, чем отличаются классы Derived1 и Derived2, то стоит расмотреть вынос данного функционала или в лямбду или в класс-функтор
Ответ написан
@vanyamba-electronics
Так у вас Base<Enum1>
и Base<Enum2> - разные классы.

Чтобы был один класс и 2 разных типа, используйте union:
typedef union {
    enum Derived1 { ...  } m_derived1;
    enum Derived2 { ... } m_derived2;
} MyEnum;

class Base {
   MyEnum m_enum;
   virtual void some_method( const MyEnum& ) = 0;
};

class Derived1 : public Base {
   void some_method( const MyEnum& eVal) {
      m_enum.m_derived1 = eVal.m_derived1;
   }
};

...
Ответ написан
Комментировать
@code_panik
Если enum не видно извне как деталь реализации, то можно так.
#include <iostream>
using namespace std;

class BaseTransport {    
public:
    virtual void Move() {        
        onArrival();            
    }
private:
    virtual void onArrival() = 0;
};

class GroundTransport : public BaseTransport {
private:
    void onArrival() override {
        cout << __PRETTY_FUNCTION__ << endl;
        state = GroundEnum::Finished;
    }
    enum class GroundEnum { Finished };    
    GroundEnum state;
};

class SeaTransport : public BaseTransport {    
private:
    void onArrival() override {
        cout << __PRETTY_FUNCTION__ << endl;
        state = SeaEnum::ReturnToBegin;
    }
    enum class SeaEnum { ReturnToBegin };
    SeaEnum state;
};

int main() {
    BaseTransport* st = new SeaTransport();
    st->Move();    
    BaseTransport* gt = new GroundTransport();
    gt->Move();
    return 0;
}
Ответ написан
Комментировать
Ваш ответ на вопрос

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

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