讲师中心 微信公众号
AI工具推荐 视频效率加速

C++实现简单的信号槽机制 _ 函数指针数组与回调管理【源码】

大磊吖_9165

大磊吖_9165

发布时间:2026-04-11 22:00:53

|

895人浏览过

|

来源于php中文网

原创

嵌入式或旧编译器不支持std::function或RTTI,且信号槽需零开销、无分配、避免虚函数,故用函数指针数组;但成员函数指针与自由函数指针类型不兼容,须统一为void()(void, int)签名,配合void*传对象指针和静态包装器实现带状态回调,注意生命周期与签名严格匹配,遍历时禁边调用边修改数组。

c++实现简单的信号槽机制 _ 函数指针数组与回调管理【源码】

为什么不用 std::function 就要手写函数指针数组

因为嵌入式环境或旧编译器(比如 GCC 4.6、MSVC 2010)不支持 std::function 或 RTTI,而信号槽又不能依赖虚函数表做动态分发——否则每个槽都要继承基类,侵入性强。函数指针数组是零开销、无分配、纯栈操作的底线方案。

但要注意:C++ 中普通成员函数指针和自由函数指针**类型不兼容**,不能混存在同一数组里。所以必须二选一:

  • 只支持 void(*)() 类型的自由函数(最简单,但无法捕获对象状态)
  • 用模板 + 静态成员函数 + void* 用户数据绕过(推荐,兼顾对象绑定与零分配)

如何用 void* + 静态函数实现带对象上下文的回调

核心思路是把对象指针塞进 void*,再通过静态函数中转调用成员函数。这不是“万能委托”,但足够轻量。

示例结构体定义:

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

struct Slot {
    void* obj;
    void (*func)(void*, int); // 统一签名:接收 obj 和一个 int 参数
};

注册时这样写:

struct MyButton {
    void onClick(int code) { /* ... */ }
    static void onClickWrapper(void* obj, int code) {
        static_cast<MyButton*>(obj)->onClick(code);
    }
};
// 注册
Slot s = {&btn, &MyButton::onClickWrapper};

容易踩的坑:

  • obj 指针生命周期必须长于槽的调用周期,否则野指针
  • 所有 func 必须严格匹配签名,C++ 不检查 void(*)(void*, int) 和 void(*)(int) 的兼容性
  • 不能用 lambda(即使不捕获,非静态 lambda 也无法转成函数指针)

信号触发时怎么安全遍历并调用槽数组

不能边遍历边删——这是多线程和单线程都存在的经典陷阱。常见错误是循环中调用 disconnect() 导致数组收缩、索引错位甚至越界读。

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载

正确做法是两阶段处理:

  • 第一遍:标记待移除项(比如置 func = nullptr)
  • 第二遍:压缩数组(memmove 或手动拷贝),或用独立的“待清理列表”延迟释放

单线程下最简方案:

for (int i = 0; i < count; ++i) {
    if (slots[i].func) {
        slots[i].func(slots[i].obj, value);
    }
}
// 再扫一遍清理空槽(可选)

性能影响:每次触发都是 O(n),不适合高频小信号(如每帧 1000+ 次 emit)。这时应换哈希表或信号分组,但那就超出“简单”范畴了。

为什么不要在槽里调用 disconnect() 或 connect()

因为你的槽数组很可能正在被 emit() 的 for 循环迭代。此时修改数组长度或内容,会直接破坏循环逻辑——不是崩溃就是跳过某些槽。

真实场景中常遇到的问题:

  • UI 按钮点击后立即 disconnect() 自己,结果下一次点击没响应(实际是这次就漏掉了)
  • 槽里又触发另一个信号,形成递归 emit,而数组在中间被改写

解决办法只有两个:

  • 用标志位延迟处理,比如设 pending_disconnect = true,等 emit 返回后再清理
  • 彻底禁止槽内修改连接关系,把解绑逻辑提到上层事件循环中

这看起来约束强,但正是“简单信号槽”能保持确定性的代价——它不模拟 Qt 那种队列化投递,也不引入额外内存分配或锁。

热门AI工具

更多
WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

UP简历
UP简历 Hot

一款AI办公效率工具,主要用于基于AI技术的免费在线简历制作工具,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

切问学术

切问学术是一款AI论文写作工具,复旦大学NLP团队推出的AI学术智能体。

PixPix
PixPix Hot

PixPix是一款面向电商视觉生产的AI商品图生成工具。

Atoms
Atoms Hot

Atoms是一款AI智能体工具,第一支自动构建真实业务的 AI 团队。

立刻MV
立刻MV Hot

立刻MV是一款AI文本写作工具,AI 音乐视频(MV)创作工具。

相关专题

更多
C++ Qt图形开发
C++ Qt图形开发

本专题专注于 C++ Qt框架在图形界面开发中的应用,系统讲解窗口设计、信号与槽机制、界面布局、事件处理、数据库连接与跨平台打包等核心技能,通过多个桌面应用项目实战,帮助学员快速掌握 Qt 框架并独立完成跨平台GUI软件的开发。

4802

2025.08.15

C++桌面程序开发
C++桌面程序开发

本专题聚焦 C++ 在桌面端图形界面应用开发中的实战应用,系统讲解 Qt 框架的信号与槽机制、界面布局管理、事件响应、数据交互、样式美化与多窗口应用设计等核心知识。通过实战案例(如记事本应用、数据管理工具、系统监控面板),帮助学习者掌握 从UI设计到完整桌面软件开发的C++工程化能力。

1334

2025.10.23

C++ 图形界面开发基础(Qt方向)
C++ 图形界面开发基础(Qt方向)

本专题系统讲解 使用 C++ 与 Qt 进行图形界面(GUI)开发的核心技能,内容涵盖 Qt 项目结构、窗口组件、信号与槽机制、事件处理、布局管理、资源管理,以及跨平台编译与打包流程。通过多个小型桌面应用实战案例,帮助学习者掌握从界面设计到功能实现的完整 GUI 开发能力。

1421

2025.12.05

golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

4654

2025.06.09

golang结构体方法
golang结构体方法

本专题整合了golang结构体相关内容,请阅读专题下面的文章了解更多。

4791

2025.07.04

string转int
string转int

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

6259

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

3045

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

3928

2025.08.29

OpenJDK JVM参数怎么调优
OpenJDK JVM参数怎么调优

Java应用运行缓慢,如何调整JVM参数?本专题介绍OpenJDK JVM性能调优的基本流程,涵盖性能指标确认、运行数据采集、内存配置和垃圾回收分析,帮助你先定位瓶颈,再通过对照测试验证效果,避免直接套用参数而影响应用稳定性。

20

2026.10.16

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习

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

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn