用C++来实现有限状态机(附代码)

💡 原文中文,约3200字,阅读约需8分钟。
📝

内容提要

本文详细介绍了C++有限状态机的要素和使用函数指针实现,通过学生日常生活案例演示了实现步骤,并总结了C++有限状态机的实现。

🔎

延伸解读

状态转移表:FSM的核心数据结构

文章使用vector存储FSMItem对象来构建状态转移表,每个FSMItem包含现态、事件、动作函数指针和次态。这种设计将状态转移逻辑集中在一处,便于维护和扩展。当事件发生时,FSM遍历表查找匹配项,执行动作并更新状态。这种表驱动方式比大量switch-case更清晰,但线性查找在状态较多时可能影响性能,可考虑用哈希表优化。

函数指针实现动作的优缺点

文章通过静态成员函数指针来关联状态转移时的动作,如getUp、go2School等。函数指针使用简单,无需继承和多态,适合轻量级FSM。但静态函数无法直接访问对象状态,所有动作只能打印信息,缺乏实际业务逻辑的灵活性。若动作需要访问上下文数据,可能需要改用std::function或成员函数指针,并传递上下文参数。

测试循环与事件模拟的局限性

测试代码使用while(1)循环和testEvent函数轮换事件,模拟事件发生并观察状态变化。这能验证基本转移逻辑,但事件序列固定,未覆盖异常事件或非法转移。实际应用中,FSM应处理未定义事件(如忽略或报错),并考虑状态转移的完整性检查。此外,循环无退出条件,仅用于演示,生产代码需设计终止机制。

❓

Q&A

有限状态机的四大要素是什么?

有限状态机的四大要素是:现态(当前所处状态)、次态(条件满足后即将转移的下一个状态)、动作(满足某个事件时执行的操作,执行后可转移到另一状态或保持原状态)、条件(转移状态所需的条件,满足时触发动作或状态转移)。

如何用C++函数指针实现有限状态机?

使用C++函数指针实现有限状态机的方法:定义状态枚举和事件枚举,创建FSMItem类(包含现态、事件、次态和动作函数指针),创建FSM类(包含状态转移表vector,提供初始化、状态转移和事件处理函数),最后测试FSM。通过函数指针在事件触发时执行相应动作并转移状态。

FSMItem类在有限状态机中起什么作用?

FSMItem类表示状态转移表中的一个条目,包含现态(_curState)、事件(_event)、次态(_nextState)以及动作函数(如getUp、go2School等)。它封装了状态转移的条件和动作,供FSM类查询和执行。

FSM类如何根据事件处理状态转移?

FSM类维护一个状态转移表(vector<FSMItem*>),在handleEvent函数中,根据当前状态和传入的事件遍历转移表,找到匹配的FSMItem后,执行其动作函数,并调用transferState更新当前状态为次态。

文章中用学生日常生活案例演示了哪些状态?

案例中学生的日常生活状态包括:起床(GETUP)、上学(GOTOSCHOOL)、吃午饭(HAVELUNCH)、做作业(DOHOMEWORK)、睡觉(SLEEP)。这些状态之间通过事件(EVENT1、EVENT2、EVENT3)触发转移。

实现有限状态机的步骤有哪些?

实现步骤包括:1. 绘制状态转移图;2. 创建FSMItem类(定义状态、事件、动作函数);3. 创建FSM类(初始化状态转移表、实现状态转移和事件处理);4. 测试FSM(模拟事件触发,验证状态转移和动作执行)。

🏷️

标签

➡️

继续阅读