0

0

C++怎么实现状态机_C++行为控制教程【逻辑】

裘德小鎮的故事

裘德小鎮的故事

发布时间:2026-02-22 17:46:45

|

137人浏览过

|

来源于php中文网

原创

优先用 class 封装状态机;函数指针数组仅适用于极简无状态嵌入式场景,c++ 中易失控、难维护、无法存上下文,而 class 可整合状态、逻辑、守卫条件并支持编译器优化。

c++怎么实现状态机_c++行为控制教程【逻辑】

状态机该用类封装还是函数指针数组

直接说结论:优先用 class 封装,别碰裸的函数指针数组。后者看着轻量,实际一加条件分支、状态间数据传递、调试日志,立刻失控。

函数指针数组适合只有 3–4 个无状态跳转的嵌入式小场景(比如 LED 模式切换),但 C++ 里几乎没优势:没法存上下文,不能重载,std::function 一上反而更重;而 class 可以把状态变量、转换逻辑、守卫条件全收在内部,编译器还能做内联优化。

  • 错误现象:void (*transitions[5])(void) 改着改着变成“谁调用了谁”都理不清,加个新状态就得全局改数组长度和索引常量
  • 实操建议:每个状态建一个私有方法,如 handle_idle()handle_running(),用 enum class State { Idle, Running, Paused } 管理当前值
  • 注意 switch (state) 不要漏 default 分支——C++ 不保证枚举值连续,未定义行为可能静默跳到错误地址

如何避免状态跳转时的数据竞争

多线程下最常踩的坑不是状态值本身,而是「状态已变,但对应数据还没就绪」。比如从 Connecting 切到 Connected,网络句柄却仍是空指针。

根本解法不是加锁,而是让状态变更成为原子操作:状态字段和它依赖的数据必须一起更新,且对外不可见中间态。

立即学习C++免费学习笔记(深入)”;

AI Home Tab
AI Home Tab

把你喜欢的AI放到首页

下载
  • 错误现象:在 set_state(State::Connected) 里只改了 m_state,后续靠外部再调 init_network() —— 这之间任何地方读状态都会拿到“假连接”
  • 实操建议:把状态变更封装成带参数的方法,如 transition_to_connected(int fd, const std::string& addr),内部先初始化数据,再改状态
  • 如果必须异步触发跳转(比如 IO 完成回调),用 std::atomic<state></state> + CAS 循环,但仅限简单状态;复杂逻辑一律走事件队列或状态机主循环

std::variant 实现状态机是否值得

值得,但仅当状态种类少(≤5)、每种状态的数据结构差异大、且你愿意放弃部分运行时灵活性。它本质是类型安全的 union,比 void* 强,比完整类封装弱。

典型适用场景:协议解析器里,不同报文类型(Handshake / DataPacket / Ack)需要完全不同的字段和处理逻辑,且不共享状态变量。

  • 错误现象:用 std::variant 存状态枚举 + 一堆 std::any 字段,结果每次访问都要 std::visit + 类型检查,性能差还难 debug
  • 实操建议:每个变体类型自己是完整 struct,含自己的处理方法,例如 struct Connected { int socket; void send(); };,状态机只管调度,不掺和数据
  • 注意 std::variant 的拷贝开销——如果某个状态携带大对象(如 std::vector<uint8_t></uint8_t>),频繁切换会触发内存分配,此时不如用指针 + std::unique_ptr

为什么 switch-case 状态机容易漏处理边界

因为人脑不擅长穷举所有输入组合。尤其当状态转移受多个条件影响(比如 “收到包 && 校验失败 && 重试次数 switch 套 if 很快变成意大利面条。

真正可靠的写法是把转移逻辑显式建模:用二维表(std::map<:pair event>, State></:pair>)或策略函数对象,让编译器/静态分析能帮你抓漏。

  • 错误现象:新增一个 Event::Timeout,只在 Running 分支加了处理,忘了 IdlePaused 下也要响应——运行时崩溃前毫无提示
  • 实操建议:定义所有合法 Event 枚举,在每个状态处理函数末尾加 assert(false) 或抛异常,确保未覆盖路径不会静默忽略
  • 更稳的做法:用编译期检查,比如 std::array<:array num_events>, NUM_STATES></:array>,初始化时填满,链接时报错提醒缺项

状态机最难的从来不是写跳转逻辑,而是让“不可能发生的状态”真的不可能发生——这需要设计时就堵死隐式假设,而不是靠测试去撞。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

810

2023.08.02

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1557

2023.10.24

if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

826

2023.08.22

switch语句用法
switch语句用法

switch语句用法:1、Switch语句只能用于整数类型,枚举类型和String类型,不能用于浮点数类型和布尔类型;2、每个case语句后面必须跟着一个break语句,以防止执行其他case的代码块,没有break语句,将会继续执行下一个case的代码块;3、可以在一个case语句中匹配多个值,使用逗号分隔;4、Switch语句中的default代码块是可选的等等。

559

2023.09.21

Java switch的用法
Java switch的用法

Java中的switch语句用于根据不同的条件执行不同的代码块。想了解更多switch的相关内容,可以阅读本专题下面的文章。

435

2024.03.13

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

550

2023.09.20

c语言union的用法
c语言union的用法

c语言union的用法是一种特殊的数据类型,它允许在相同的内存位置存储不同的数据类型,union的使用可以帮助我们节省内存空间,并且可以方便地在不同的数据类型之间进行转换。使用union时需要注意对应的成员是有效的,并且只能同时访问一个成员。本专题为大家提供union相关的文章、下载、课程内容,供大家免费下载体验。

129

2023.09.27

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

810

2023.08.02

pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法

本专题系统整理pixiv网页版官网入口及登录访问方式,涵盖官网登录页面直达路径、在线阅读入口及快速进入方法说明,帮助用户高效找到pixiv官方网站,实现便捷、安全的网页端浏览与账号登录体验。

1030

2026.02.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 10万人学习

C 教程
C 教程

共75课时 | 4.9万人学习

C++教程
C++教程

共115课时 | 18.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号