c++ - 使用函数指针作为 UI-Button 回调的缺点
问题描述
我目前正在创建自己的基于 SFML 的 GUI-Library。目前我正在研究一个按钮。因此,在创建按钮时,您还必须指定一个回调,它是一个函数,在按钮单击时执行。
现在,我正在回答我只使用指向函数的指针作为按钮回调的缺点是什么,因为我不知道任何流行的 GUI-Library 也可以这么简单地做到这一点。如果回调函数是一个漫长的过程,我会在一个新线程中执行它,但我现在不确定。
那么,不使用这种简单解决方案的原因是什么,尤其是更好的方法呢?
解决方案
这是一个棘手的问题!
函数指针在发送方很容易实现,但在接收方很难使用,因为它们没有任何上下文。
一个问题是函数指针不能指向成员函数。这就是为什么您经常看到(C 风格)框架将任意参数传递void *userData
给它们的回调,因此您可以转换this
指针并以这种方式检索它。这仍然需要您编写一个静态包装函数来将指针转换回并调用成员函数。
更现代的解决方案是使用std::function
. 这可以包含常规函数指针、成员函数指针,还可以包含 lambda 或仿函数。
但是,当您像这样(或以其他方式)添加上下文时,您很快就会遇到生命周期的困难。当接收类在发送者之前被销毁时,应该发生什么?如果您什么都不做,这种情况将导致未定义的行为。一种解决方案是在接收方跟踪接收方订阅了哪些事件,并在接收方被销毁之前解除绑定。这需要双向进行:当发送者被销毁时,它还需要通知接收者它应该忘记发送者,否则接收者稍后会尝试解除绑定不再存在的事件。
而且我什至还没有开始考虑多线程...
有图书馆以各种方式解决这些问题,例如eventpp
(只是通过网络搜索找到的,这不是背书)。
另一个值得一提的是 Qt 工具包,它甚至为 C++ 语言编写了自己的小信号和插槽扩展(实现为代码生成器和一堆宏),以非常符合人体工程学的方式解决这个问题。
推荐阅读
- python - 如何在 Django 序列化器中获取请求用户 ID?
- powershell - 仅在戴尔机器上强制更新驱动程序
- javascript - 如何为js函数添加定时器一段时间然后显示消息
- python - PySimpleGUI 日历/日期选择器的字体大小
- asp.net-mvc - 文件上传错误“对象引用未设置为对象实例”
- java - 从 React 和 Spring Boot 上传 CSV 文件
- javascript - 将新的自定义 api 方法定义添加到 Jest 命名空间
- r - 绘图时如何将日期值的缩放标签从数字格式更改为日期格式?
- r - 逐组数据帧的 Cumsum
- python - 为什么我的 Armstrong Number Checker Program 的“number”变量最后会改变值?