C++ 回调函数
1|0什么是回调函数
举一个例子
你入住一家酒店,这个酒店前台提供了叫醒服务,你可以自定义叫醒时间和叫醒服务。对于前台来说,叫醒时间只是变量,但是叫醒服务可以认为是一个函数。
这种把函数作为一个参数传递进另一个函数的函数叫做回调函数。被传入函数的函数叫做中间函数。下面实现了一个简单的python例子
2|0如何写形参表
2|1函数指针
当我们定义一个函数时,函数的变量名就是一个函数指针,但是我们如何定义函数指针。
初始化函数指针
简化定义
2|2std::function
std::function
是一个通用的函数包装器,可以存储可调用对象,如函数指针、lamda表达式、bind表达式、仿函数,类成员函数、类成员变量。使用std::function
可以实现函数回调目的。
函数指针
既然可以用std::function
实现,也就可以用模板推到出这个类型
lambda
同样也可以用模板推到出来。
仿函数
当用户定义的类重载了函数调用运算符operator()
时,它就成为了函数对象类型,这样的一个类就被称为仿函数(functor)。下面是一个简单的例子。
仿函数通常不需要实现构造函数和析构函数。
实现回调函数
当然了,由于这里的Add
是一个类,因此也我们可以直接用模板表示
std::bind
std::bind
可以看作一个通用的函数适配器,它接受一个可调用对象,生成一个新的可调用对象来适应原对象的参数列表。std::bind
将可调用对象与其参数一起进行绑定,绑定后的结果可以使用std::function
保存。std::bind
主要有以下两个作用:
- 将可调用对象和其参数绑定成一个仿函数;
- 只绑定部分参数,减少可调用对象传入的参数。
基础的使用方法如下
f
必须是可调用对象,args
是参数列表,对于未绑定的参数可以可以用std::placeholders
的占位符_1,_2,_3
等替换。
用std::bind
表达式实现回调函数的方法与上述类似,就不在赘述了。
我们要明确一点,std::bind
默认是传值,并不是传引用,因此会出现一些特殊情况。
如果std::bind
需要绑定静态成员函数和普通函数一样。但如果要绑定非静态成员函数则有一点不同,因为非静态成员函数还有this
指针。具体实现看下面的例子。
首先这个例子中的&
都是取地址符。
&A::print
,是因为 C++ 中,成员函数指针必须通过 &ClassName::MemberFunction
的形式显式获取。
再看&a
,为什么需要写a
?因为在std::bind
在绑定成员函数时,必须要知道调用该函数的对象。
为什么需要取地址符。其实这里并不一定需要取地址。只是如果只写a
就是传值,会触发拷贝构造。
我们看下面的例子。
我们运行就会发现,a.pirnt()
的结果时x = 1
,而b.print()
的结果是x = 4
。这是因为f
在绑定时会触发拷贝构造,因此f()
就不会修改a.x
的值。而g
绑定的对象就是b
。
当然了对于这里的&b
也可以用std::ref()
代替。
请注意,这里的形参实际上是一个指针类型,因此可以用std::ref
代替。但并不等于&
可以代替std::ref
。比如下面这种情况。
正确的绑定应当是
如果这里使用了&x
就会导致类型不匹配。
再提到另一点,如果需要std::bind
绑定仿函数有两种方法。
当然了,如果要保留对象的状态,也可采用std::ref
传引用。
__EOF__

本文链接:https://www.cnblogs.com/PHarr/p/18732716.html
关于博主:前OIer,SMUer
版权声明:CC BY-NC 4.0
声援博主:如果这篇文章对您有帮助,不妨给我点个赞
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律