我需要一个模板类来将方法传递给基类吗?

时间:2017-01-21 16:46:45

标签: c++ templates dictionary inheritance

我正在编写一个有限状态机(FSM)类,它应该从各种其他派生类继承(作为Arduino项目的一部分)。 派生类需要将布尔方法传递给基本FSM类触发状态更改。方法保存在地图中。在主循环中调用它们时,它们将通过映射中的方法来查看状态更改是否适用。

由于FSM类需要调用派生类的方法,因此我根据派生类的类将FSM类编写为模板类。在(T& obj)上应用该方法的对象被传递给构造函数:

template <class T> class FiniteStateMachine {
public:
  FiniteStateMachine(int numberOfStates, int initialState, T& obj);

  typedef bool (T::*TransitionCondFunction)(void);
  void addTransition(int fromState, int toState,  TransitionCondFunction transitionFunction);

  void loop();

private:
  int _numStates;
  int _state;

  T& _obj;   // the object to apply the functions on
  map<int,map<int,TransitionCondFunction>> _transitionMap;
}

template<class T>
FiniteStateMachine<T>::FiniteStateMachine(int numberOfStates, int initialState, T& obj) :
_numStates(numberOfStates), _state(initialState), _obj(obj), _transitionMap() {}

template<class T>
void FiniteStateMachine<T>::addTransition(int fromState, int toState,  TransitionCondFunction transitionFunction){
  _transitionMap[fromState][toState] = transitionFunction;
}

template<class T>
void FiniteStateMachine<T>::loop(){
  auto it = _transitionMap.find(_state);
  if (it != _transitionMap.end()){
    map<int,TransitionCondFunction> innerTransMap = it->second;
    for(typename map<int,TransitionCondFunction>::iterator iter = innerTransMap.begin(); iter != innerTransMap.end(); ++iter) {

      bool (T::*tf)(void)  = iter->second;
      // is condition for transition fullfilled?
      if ((_obj.*tf)()) {
        int toState =  iter->first;
        // ok, transit to next state
        _state = toState;
        break;
      }
    }
  }
  else {
    printf("Cannot find transition condition function for state %d\n", _state);
  }
}

具体派生类需要这样:

enum MyState {STATE0, STATE1, STATE2, NUM_STATES};

class MyTransitionClass : public FiniteStateMachine<MyTransitionClass>{
public:
  MyTransitionClass(int numberOfStates, int initialState) :
    FiniteStateMachine(numberOfStates, initialState, *this){
    addTransition(STATE0, STATE1, t1);
  }
  bool t1(){return _x>0;}

private:
  int _x = 99;
};

使用(在单元测试中)将是这样的:

TEST(FiniteStates_test, testWithInheritedClass){

  MyTransitionClass mc = MyTransitionClass(2,STATE0);
  EXPECT_EQ(STATE0, mc.getState());
  mc.loop();
  EXPECT_EQ(STATE1, mc.getState());
}

这有效,但我想知道是否还有其他选择。使用派生类作为模板类型来实例化模板类并不“感觉”最佳。

有什么建议吗?

0 个答案:

没有答案