c++ - 将“this”从父类方法转换为子类方法是一种好习惯吗?
问题描述
我正在实现一个非常基本的基类来运行有限状态机。这是我所做的......
/**
* @class FSM
* @brief This class is a base class for an object that wants to run a Finite State Machine.
* That object, let's say States, would need to inherit from FSM<States>,
* and its methods would then be available as state actions of the state machine.
*/
template<typename States>
class FSM
{
public :
/**
* @typedef StateAction is an alias for a pointer to a method of States, only callable that can be a state of the FSM
*/
typedef void(States::*StateAction)(void);
/**
* @fn FSM(States* states, StateAction initial_state_action = nullptr)
* @brief Constructs a FSM object whose actions are of type StateAction
*/
FSM(States* states, StateAction initial_state_action = nullptr)
:
m_states(states),
m_state_action(initial_state_action),
m_is_entering_state(true)
{}
/**
* @fn bool update()
* @brief Performs an iteration of the FSM
* @returns true if and only if the FSM has a state to run
*/
bool update()
{
if(m_states && m_state_action)
{
auto previous_action = m_state_action;
(m_states->*m_state_action)();
m_is_entering_state = (m_state_action != previous_action);
}
return m_state_action != nullptr;
}
protected :
/**
* @fn void setState(StateAction state_action)
* @brief Change the state of the FSM
* @param[in] state_action Method of States that implements the new state behavior (nullptr stops the FSM)
*/
void setState(StateAction state_action)
{
m_state_action = state_action;
}
/**
* @fn bool isEnteringState() const
* @brief Tells whether the current state has just be entered or is looping, waiting for a transition
* @returns] true if and only if the current state hasn't yet been executed since it has been changed
*/
bool isEnteringState() const
{
return m_is_entering_state;
}
private :
States* m_states; //!< Pointer to the child class that implements the States of the FSM
StateAction m_state_action; //!< Pointer to the method of States that implements the current state behavior
bool m_is_entering_state; //!< Tells whether the current state has just be entered or is looping, waiting for a transition
};
...以及它的用途:
class States : public FSM<States>
{
public :
States()
:
FSM<States>(this, &States::state1)
{}
void state1()
{
// Actions to perform when entering the state
if(isEnteringState()) cout << "Entering ";
// Actions to perform constantly (regulate a system, detect events, etc...)
cout << __func__ << endl;
// Transitions to other states
bool is_event_detected = true;
if(is_event_detected) setState(&States::state2);
}
void state2()
{
if(isEnteringState()) cout << "Entering ";
cout << __func__ << endl;
bool is_exit_detected = true;
if(is_exit_detected) setState(nullptr);
}
};
int main()
{
States fsm;
bool is_fsm_running = true;
while(is_fsm_running)
{
is_fsm_running = fsm.update();
}
return EXIT_SUCCESS;
}
在 FSM 中存储 m_states(指向实现状态的派生对象的指针)的唯一目的是在 update() 中调用 m_state_action,它是指向派生对象方法的指针。相反,我想知道使用 static_cast 将其(FSM* 类型)转换为 States* 是否是一种好习惯?
(static_cast<States*>(this)->*m_state_action)();
行为是否明确?(我知道它适用于 mingw 7.30)
另外,作为一个附带问题,用一个作为其子类的类模板 FSM 看起来有点奇怪(类状态:公共 FSM)......我可以用不同的方式做吗?
解决方案
是的,在两种情况下它是合法的:
States
必须公开地和非虚拟地继承自FSM<States>
.您的设计已经要求这种使用模式,但最好添加一个
static_assert
来强制执行此要求。该对象实际上是 的一个实例
States
。即使不是不可能,也很难预防
struct BogusStates : FSM<TrueStates> {};
您至少可以
FSM<States>
通过给它一个protected
构造函数来防止任何人直接实例化。
推荐阅读
- node.js - 在 Mongoose 中更新嵌套对象
- javascript - Joi:根据其他键的值过滤值
- excel - VBA代码从工作表上的下拉菜单中选择值并转到与同一工作表上的标题具有相同值的列 - Excel 2010
- react-native - React Native:在特定的深度链接 URL 处打开推送通知
- angular - RxJS 的 Observables 数组,带有要保存的额外数据
- r - 取消嵌套不同大小的相关列表列
- python - 检测列表中的连续整数 [Python 3]
- svg - 如何将svg图片显示为光标
- api - TypeORM - 获取提供的 id 的对象,这是一个关系
- python - 我如何删除
从输出