新闻中心

C++如何实现一个状态机_C++使用状态模式或表驱动法管理对象状态

2025-12-06
浏览次数:
返回列表
C++中实现状态机有两种常用方法:状态模式通过类和多态封装状态行为,适合逻辑复杂、扩展需求高的场景;表驱动法用状态转移表定义“状态+事件→动作”,适用于状态事件固定、性能要求高的场合。状态模式扩展性强但类数量多;表驱动结构清晰、效率高但灵活性差。选择依据包括逻辑复杂度、状态可变性及团队习惯,也可结合使用以兼顾灵活性与性能。

c++如何实现一个状态机_c++使用状态模式或表驱动法管理对象状态

在C++中实现状态机,常见的方式有两种:状态模式(State Pattern)表驱动法(Table-Driven Approach)。两者各有优势,适用于不同场景。下面分别介绍其实现方法与使用建议。

状态模式:面向对象的经典设计

状态模式通过类和多态机制来管理对象的状态转换,适合状态行为差异大、逻辑复杂的系统。

核心思想是将每个状态封装成独立的类,对象的行为随状态改变而动态切换。

示例代码:

定义一个抽象状态基类,再为每种状态提供具体实现。

#include <iostream>
#include <memory>

class Context; // 前向声明

// 抽象状态类
class State {
public:
    virtual ~State() = default;
    virtual void handle(Context& ctx) = 0;
};

// 具体状态类
class ConcreteStateA : public State {
public:
    void handle(Context& ctx) override;
};

class ConcreteStateB : public State {
public:
    void handle(Context& ctx) override;
};

// 上下文类,持有当前状态
class Context {
private:
    std::shared_ptr<State> state_;
public:
    Context(std::shared_ptr<State> state) : state_(state) {}

    void request() {
        state_->handle(*this);
    }

    void changeState(std::shared_ptr<State> new_state) {
        state_ = new_state;
    }
};

// 实现具体状态的行为
void ConcreteStateA::handle(Context& ctx) {
    std::cout << "处理状态 A 的逻辑\n";
    // 可以触发状态转移
    ctx.changeState(std::make_shared<ConcreteStateB>());
}

void ConcreteStateB::handle(Context& ctx) {
    std::cout << "处理状态 B 的逻辑\n";
    ctx.changeState(std::make_shared<ConcreteStateA>());
}

使用方式:

```cpp int main() { auto ctx = Context(std::make_shared()); ctx.request(); // 输出: 处理状态 A 的逻辑 ctx.request(); // 输出: 处理状态 B 的逻辑 return 0; } ```

优点:扩展性强,新增状态只需添加新类;符合开闭原则。

缺点:类数量增多,结构略复杂。

表驱动法:简洁高效的状态转换

表驱动法用二维数组或映射结构描述“当前状态 + 事件 → 下一状态 + 动作”,适合状态和事件有限且明确的场景。

Moshi Chat Moshi Chat

法国AI实验室Kyutai推出的端到端实时多模态AI语音模型,具备听、说、看的能力,不仅可以实时收听,还能进行自然对话。

Moshi Chat 160 查看详情 Moshi Chat

常用于协议解析、控制流程等对性能要求较高的场合。

示例代码:

#include <iostream>
#include <functional>
#include <map>

enum State { IDLE, RUNNING, PAUSED };
enum Event { START, STOP, PAUSE, RESUME };

struct Transition {
    State next_state;
    std::function<void()> action;
};

class StateMachine {
private:
    State current_state_;
    std::map<std::pair<State, Event>, Transition> table_;

public:
    StateMachine() : current_state_(IDLE) {
        // 初始化状态转移表
        table_[{IDLE, START}]     = {RUNNING, []{ std::cout << "启动设备\n"; }};
        table_[{RUNNING, PAUSE}]  = {PAUSED,  []{ std::cout << "暂停运行\n"; }};
        table_[{PAUSED, RESUME}]  = {RUNNING, []{ std::cout << "恢复运行\n"; }};
        table_[{RUNNING, STOP}]   = {IDLE,    []{ std::cout << "停止设备\n"; }};
        table_[{PAUSED, STOP}]    = {IDLE,    []{ std::cout << "强制停止\n"; }};
    }

    void dispatch(Event e) {
        auto key = std::make_pair(current_state_, e);
        auto it = table_.find(key);
        if (it != table_.end()) {
            if (it->second.action) {
                it->second.action();
            }
            current_state_ = it->second.next_state;
        } else {
            std::cout << "无效的状态转移: ";
            // 简单打印状态和事件
            printStateEvent(current_state_, e);
        }
    }

    void printCurrentState() const {
        switch (current_state_) {
            case IDLE:     std::cout << "当前状态: IDLE\n";     break;
            case RUNNING:  std::cout << "当前状态: RUNNING\n";  break;
            case PAUSED:   std::cout << "当前状态: PAUSED\n";   break;
        }
    }

private:
    void printStateEvent(State s, Event e) {
        const char* s_str[] = {"IDLE", "RUNNING", "PAUSED"};
        const char* e_str[] = {"START", "STOP", "PAUSE", "RESUME"};
        std::cout << s_str[s] << " + " << e_str[e] << "\n";
    }
};

使用方式:

```cpp int main() { StateMachine sm; sm.printCurrentState(); // IDLE sm.dispatch(START); // 启动设备 sm.printCurrentState(); // RUNNING sm.dispatch(PAUSE); // 暂停运行 sm.dispatch(RESUME); // 恢复运行 sm.dispatch(STOP); // 停止设备 sm.printCurrentState(); // IDLE return 0; } ```

优点:结构清晰,易于维护和生成代码;性能好。

缺点:状态和事件必须提前确定;动作函数若复杂则不易管理。

如何选择合适的方法?

根据项目需求权衡:

  • 业务逻辑复杂、状态行为差异明显 → 推荐使用状态模式
  • 状态和事件固定、追求简洁高效 → 推荐使用表驱动法
  • 需要运行时动态配置状态转移 → 表驱动更灵活
  • 团队熟悉设计模式 → 状态模式更容易协作理解

也可以结合使用:用表驱动管理状态跳转,用函数对象绑定状态模式中的处理逻辑。

基本上就这些。两种方法都能有效管理对象状态,关键看场景是否匹配。

以上就是C++如何实现一个状态机_C++使用状态模式或表驱动法管理对象状态的详细内容,更多请关注其它相关文章!


# 如何使用  # 罗甸seo网站优化公司  # 海宁网站建设银行工作  # 长春公司网站建设报价  # 兰州网站建设实验报告  # 泰州网站优化经验师招聘  # 福建关键词排名怎么样  # seo内容收录原理  # 营销推广好学吗  # 如何推广网站选择c火13星规范  # 重庆网站建设来沛宣  # 都能  # 还能  # 操作方法  # app  # 有两种  # 适用于  # 推荐使用  # 如何实现  # 面向对象  # 多态  # red  # stream  # switch  # ios  # c++  # ai  # mac 


相关栏目: 【 科技资讯46185 】 【 网络学院92790


相关推荐: J*aScript数据结构转换:将对象数组按类别分组  C++如何操作大型数据集_使用C++流式处理(Streaming)技术避免一次性加载大文件  LINUX下如何进行磁盘分区_fdisk与parted工具在LINUX中的使用对比  PHP URL参数传递与500错误调试指南  AO3网页版合集入口 Archive of Our Own同人作品浏览指南  处理动态列数据:J*a ArrayList的正确初始化与字符累加教程  J*a递归快速排序中静态变量的状态管理与陷阱  顺丰快递查询系统 官方正版查询入口  小米14应用无法联网原因分析_小米14网络权限修复  今日头条怎么同步内容到抖音_今日头条内容同步到抖音教程  神经网络二分类模型训练异常:高损失与完美验证准确率的排查与修正  C++的std::forward_list怎么用_C++ STL中单向链表容器的特点与应用  sublime怎么格式化代码_sublime代码美化与一键排版插件配置  2025AO3夸克浏览器通道_AO3手机HTTPS安全入口分享  html怎么在cmd下运行php文件_cmd运行html中php文件方法【教程】  Go语言中高效处理x-www-form-urlencoded表单数据  Win10自动更新怎么关闭 Win10永久关闭系统更新的两种方法【终极版】  高德地图公交到站提醒失败如何解决 高德提醒权限设置  C++ explicit关键字防止隐式转换_C++构造函数安全规范  Python vgamepad库按键模拟:正确使用XUSB_BUTTON常量  如何在J*a中使用Locale处理多语言环境  照顾宝贝2小游戏免费秒玩入口  如何在复杂的电商平台中优雅地管理共享资源并确保正确重定向,使用spryker-shop/resource-share-page模块助你一臂之力  蛙漫官方正版入口 蛙漫网页在线全集免费观看  12306选座系统怎么选连座_12306选座多人连坐操作方法  J*aScript map 方法中处理循环元素为空数组的策略  抖音怎么赚钱_抖音创作者变现方法与途径指南  windows10怎么查看本机ip_windows10命令提示符ipconfig使用  红果短剧网页版官网入口 官方最新网址发布  如何在更新Composer依赖后自动运行测试_使用post-update-cmd钩子触发PHPUnit  在Go开发中优雅管理ListenAndServe进程:GoSublime集成方案  4399免费游戏网址入口 4399小游戏免费入口点开即玩  我的世界官方游戏入口 我的世界官网平台直达链接  J*a 递归快速排序中静态变量的状态管理与陷阱  搜狗浏览器如何使用密码生成器创建强密码 搜狗浏览器内置密码安全工具  大象笔记网页版入口 印象笔记网页版登录入口  MinIO大规模对象列表性能瓶颈深度解析与外部元数据管理策略  在J*a中如何使用BigDecimal进行高精度计算_BigDecimal类应用指南  初次安装JDK时环境变量如何正确配置_J*A_HOME与PATH设置规则讲解  拷贝漫画电脑版官网入口 拷贝漫画(PC版)在线直达  J*aScript打印功能_j*ascript输出控制  Spring Boot内嵌服务器与J*a EE全栈特性:选择与部署策略  Pandas DataFrame:高效添加条件计算列  汽水音乐车机版8.9下载 汽水音乐车机版8.9版本安装入口  NRF24L01数据传输深度解析:解决大载荷接收异常与分包策略  解决J*aScript中重复选择项的确认对话框显示问题  Composer的 "conflict" 字段有什么用_如何声明不兼容的包以避免依赖冲突  mc.js游戏直达 mc.js网页免下载版本秒进地址  Yandex官方入口网址 Yandex俄罗斯搜索引擎最新在线地址  写好的html代码怎么运行出来_运行写好的html代码方法【教程】 

搜索