新闻中心
c++如何实现一个状态机_c++状态模式与有限状态机(FSM)【设计模式】
C++中实现状态机主要有三种方式:状态模式(面向对象、可扩展)、枚举+switch FSM(轻量、零开销)、状态表驱动FSM(规则外化、易维护);应据场景复杂度与性能需求选型,强调状态切换顺序、解耦与可测性。

在C++中实现状态机,核心是把“对象的行为随状态变化而变化”这一逻辑显式建模。常用两种思路:一种是用状态模式(State Pattern)——面向对象、可扩展、适合复杂状态逻辑;另一种是有限状态机(FSM)——更轻量、常基于枚举+switch或状态表驱动,适合嵌入式或性能敏感场景。两者不是互斥,而是适用场景不同。
用状态模式实现可维护的状态机
状态模式把每个状态封装成独立类,让状态切换和行为委托给具体状态对象,避免大段if-else或switch,也便于新增状态。
关键点:
- 定义统一的State抽象基类,声明所有状态共有的接口(如
handleEvent()) - 为每个具体状态(如
IdleState、RunningState)实现子类,各自封装行为逻辑 - 上下文类(如
Context)持有一个State*指针,负责委托调用,并在需要时切换状态 - 状态切换由当前状态决定(推荐),或由Context协调(需谨慎避免循环依赖)
示例片段:
struct State {
virtual ~State() = default;
virtual void onEventA(Context&) = 0;
virtual void onEventB(Context&) = 0;
};
<p>struct IdleState : State {
void onEventA(Context& ctx) override { ctx.setState(std::make_unique<RunningState>()); }
void onEventB(Context&) override { /<em> 忽略 </em>/ }
};</p><p>struct Context {
std::unique<em>ptr<State> state</em>;
Context() : state_(std::make_unique<IdleState>()) {}
void setState(std::unique<em>ptr<State>&& s) { state</em> = std::move(s); }
void handleA() { state_->onEventA(*this); }
};用枚举+switch实现轻
量FSM
适合状态少、事件简单、追求零开销抽象的场景(如协议解析、设备驱动)。用enum class定义状态,用成员变量保存当前状态,用switch分发事件处理。
优点:无虚函数开销、内存紧凑、调试直观;缺点:状态增多后易臃肿,行为复用性差。
建议写法:
AI Code Reviewer
AI自动审核代码
112
查看详情
- 将状态转移逻辑集中在一个
transition()函数中,返回新状态,避免在各case里分散写state_ = ... - 用
[[fallthrough]]明确表达意图,避免误触发 - 对非法状态/事件加断言或日志,便于早期发现问题
示例:
enum class FSMState { Idle, Processing, Done };
struct SimpleFSM {
FSMState state_ = FSMState::Idle;
void handleInput(char c) {
auto next = transition(state_, c);
if (next != state_) {
onExit(state_);
state_ = next;
onEnter(state_);
}
}
private:
FSMState transition(FSMState s, char c) {
switch (s) {
case FSMState::Idle: return (c == 'S') ? FSMState::Processing : s;
case FSMState::Processing: return (c == 'E') ? FSMState::Done : s;
case FSMState::Done: return s;
}
return s;
}
};用状态表驱动FSM(进阶但清晰)
把状态转移规则外化为二维表(状态 × 事件 → 新状态 + 动作),适合规则稳定、状态/事件较多的系统(如通信协议栈)。
典型结构:
- 定义事件枚举Event(如
EvStart,EvStop) - 定义状态转移表:
std::array<:array n_events>, N_STATES> table;</:array> -
Transition结构体含
next_state和action(可为函数指针或std::function) - 执行时查表+调用动作,主逻辑极度简洁
好处是业务规则与代码分离,易于配置、测试和生成;缺点是引入间接层,小项目略重。
选型建议与避坑提示
不复杂但容易忽略:
- 状态切换时,务必确保离开旧状态(
onExit)和进入新状态(onEnter)的顺序正确,尤其涉及资源释放/初始化 - 避免状态类持有Context强引用导致循环生命周期;用弱指针或回调函数解耦
- FSM中不要在状态处理函数里直接修改
state_,统一走transition路径,保证可控性和可测性 - 调试时加状态日志(如
std::cout ),比断点更高效
基本上就这些。状态机不是炫技,关键是让状态流转可读、可测、可演进。从枚举switch起步,状态变复杂了再升级到状态模式或状态表,更务实。
以上就是c++++如何实现一个状态机_c++状态模式与有限状态机(FSM)【设计模式】的详细内容,更多请关注其它相关文章!
# 这一
# 杭州正规网络推广营销
# 潍坊网站建设技术
# 廊坊租房网站建设
# 蕉城厦门seo推广
# 桐城网站优化哪家强些呀
# 奖杯SEO怎么做
# 太康本地网站建设平台
# 抖音营销推广哪家比较好
# 茶饮营销推广方法
# 郑州抖音seo方案
# 两种
# 回调函数
# 进阶
# 如何将
# 如何使用
# 转换为
# 如何实现
# 面向对象
# 子类
# 回调
# switch
# c++
# 栈
相关栏目:
【
科技资讯46185 】
【
网络学院92790 】
相关推荐:
漫蛙漫画登录站点 漫蛙2正版漫画快速访问
React/Next.js中实现列表项的动态移动与状态管理:兼论唯一键的重要性
使用 Pandas 高效处理 .dat 文件:数据清洗与数值计算实战
为什么简单的XML文件也会解析失败? 检查隐藏的非打印字符(如BOM)的方法
如何提高微信支付的安全性_微信支付安全防护与设置建议
抖音创作助手登录入口_抖音创作辅助工具官网直达
LINUX的perf命令入门_LINUX官方性能分析工具的使用与解读
汽水音乐网页版使用入口_汽水音乐电脑版播放指南
Golang切片为何属于引用类型_Golang slice底层结构与引用语义说明
汽水音乐车机版横屏版7.1 汽水音乐车机版横屏版下载入口
12306选座怎么选到临时改签座_12306改签选座策略与步骤
如何解决电商平台定制报价请求的“黑洞”问题,SprykerQuoteRequest模块助你提升客户体验与销售效率
在J*a中如何隐藏复杂性_使用门面模式组织对象交互
C++如何检测键盘输入_C++ _kbhit与_getch函数非阻塞输入
Composer的 "licenses" 命令如何帮助你遵守开源协议_检查项目依赖的许可证合规性
谷歌邮箱网页版官方页面入口 谷歌邮箱网页端快速访问
大象笔记网页版入口 印象笔记网页版登录入口
NVIDIA股价11月重挫12%:下月有望好转 但难回5万亿美元巅峰
如何使用J*aScript精确选择并批量修改特定父元素下子链接的样式
Node.js CSV 数据处理:基于字段空值条件过滤整条记录的策略
Composer如何在生产环境安全地执行composer update
印象笔记怎样用批量导出备知识库_印象笔记用批量导出备知识库【备份方法】
“音游” × “怪文书” 题材的节奏冒险游戏 《晕晕电波症候群》确定于2026年4月发售!
随机参数递归函数的基准调用次数与时间复杂度探究
Golang如何实现微服务鉴权与权限控制_Golang微服务鉴权与权限管理实践
Win11怎么关闭触摸屏_Windows 11禁用HID符合标准触摸屏
如何在Python中使用Optional类型处理可变对象并避免Pylint警告
抖音商城签到领现金是真的吗_抖音商城签到奖励与提现说明
TikTok搜索结果不显示如何解决 TikTok搜索刷新优化方法
cad如何更改注释性对象的比例_cad注释性比例调整方法
Web Components中自定义开关组件状态同步的常见陷阱与解决方案
Golang如何通过reflect操作map_Golang reflect map操作与遍历技巧
Python Socket多播通信中指定源IP地址的实践指南
深入理解Google Cloud Datastore查询:祖先路径与数据一致性
电脑安装程序提示“错误1722”怎么办_Windows Installer服务问题解决【教程】
中兴BladeV30怎样用测距估书架层高_iPhone中兴BladeV30测距估书架层高【家装参考】
星露谷物语官网入口 星露谷物语游戏官网入口
谷歌浏览器一键优化方案_谷歌浏览器直达主页极速不卡版
Win11怎么开启高性能模式_Windows 11电源计划优化设置
微信群消息显示延迟如何解决 微信群消息刷新优化方法
composer 和 npm/yarn 在管理依赖方面有什么核心思想差异?
mysql密码锁定怎么解锁_mysql密码锁定解锁后修改密码步骤
Python中高效访问嵌套字典与列表中的键值对
漫蛙漫画网页端入口 漫蛙2官方正版漫画站点
Golang如何通过reflect获取匿名字段方法_Golang reflect匿名字段方法访问技巧
uc手机浏览器网页版入口 uc浏览器手机版便捷登录首页
Windows10怎么开启夜间模式 Windows10系统设置调整色温与亮度缓解夜间用眼疲劳【教程】
多闪网页版在线观看免费入口_多闪官网访问入口
Yandex官方入口网址 Yandex俄罗斯搜索引擎最新在线地址
Lar*el Excel导入时生成自定义递增ID的策略与实践


2025-12-15
浏览次数:次
返回列表
量FSM