C++中的回调函数

一、回调机制

1.回调定义(小A带着名片D通过途径C找到小B求他帮忙,小B不能立即解决于是收下名片D,之后的某天小B解决了小A的问题后又通过名片D告诉了小A解决方法)

2.回调方法:

①定义一个函数(普通函数即可);②将此函数的地址注册给调用者;③特定的事件或条件发生时,调用者使用函数指针调用回调函数。例如:

二、同步回调和异步回调

举例:假设有两个程序员在写代码,A程序员写底层驱动接口,B程序员写上层应用程序,然而此时底层驱动接口A有一个数据d需要传输给B,此时有两种方式:

  • 方法一:A将数据d存储好放在接口函数中,B自己想什么时候去读就什么时候去读,这就是我们经常使用的函数调用,此时主动权是B。
  • 方法二:A实现回调机制,当数据变化的时候才将通知B,你可以来读取数据了,然后B在用户层的回调函数中读取速度d,完成OK。此时主动权是A。

方法一效率较低,B不知道什么时候该去调用接口函数读取数据d。方式二由于B的读取数据操作是依赖A的,只有A叫B读数据,那么B才能读数据。

回调函数就是一个通过函数指针调用的函数。如果用户层B把函数的指针(地址)作为参数传递给底层驱动A,这个指针“在A中”为调用它所指向的函数时,我们就说这是回调函数。
注意:是在A中被调用,这里看到尽管函数是在B中,但是B却不是自己调用这个函数,而是将这个函数的函数指针通过A的接口函数传自A中了,由A来操控执行,这就是回调的意义所在。

1.基本概念

①回调可以是同步也可以是异步

②同步可以是单线程也可以是多线程

③异步必须是多线程或多进程(每个进程可以是单线程)

2.调用方法

①同步回调:把函数b传递给函数a。执行a的时候,回调了b,a要一直等到b执行完才能继续执行

②异步回调:把函数b传递给函数a。执行a的时候,回调了b,然后a就继续往后执行,b独自执行

3.例子

①同步回调

A.h(声明了SetCallBackFun()函数)

A.cpp(定义了SetCallBackFun()函数---->调用B中的函数)

B.cpp(定义了最后要调用的函数fCallBack())

示意图:

对象B通过函数指针调用了A中的函数,A中函数又调用了(参数传进来的)B中的另一个函数===》相当于B中函数2调用了B中函数1,所以叫做回调。运行结果为:

②异步回调

A.h(和同步没区别,声明了SetCallBackFun()函数)

A.cpp(定义了SetCallBackFun()函数---->通过创建线程函数调用B中的函数)

B.cpp(和同步没区别,定义了最后要调用的函数fCallBack())

示意图:

对象B通过函数指针调用了A中的函数,A创建了另一个线程来调用了B中的另一个函数。运行结果为:

③结果比较

同步回调,A需要等待B执行完成才能执行A剩余的操作,所以A:end后,B:end。

异步回调,A执行B,不必等待B结束,就执行A剩余的操作,之后B的操作也随之end。

三、注意事项

1.c++不能使用成员函数作为回调函数

①C++中this的作用:C++通过传递一个指向自身的指针this给其成员函数,从而实现成员函数可以访问C++的数据成员。因此C++类的多个实例可以共享成员函数但又有不同的数据成员。

②c++不能使用成员函数作为回调函数的原因:普通的C++成员函数都隐含了一个传递参数(即this指针),使得将一个CALLBACK型的成员函数作为回调函数时,因为隐含的this指针使得函数参数个数不匹配,从而导致回调失败。

③解决办法:

  • 直接使用普通C函数(为了实现在C函数中可以访问类的成员变量,可以使用友元操作符(friend),在C++中将该C函数说明为类的友元即可。这种处理机制与普通的C编程中使用回调函数一样);
  • 使用静态成员函数,静态成员函数不使用this指针作为隐含参数,这样就可以作为回调函数。(使用一个静态类指针作为类成员,通过在类创建时初始化该静态指针,如pThis=this,然后在回调函数中通过该静态指针就可以访问所有成员变量和成员函数了。这种处理办法适用于只有一个类实例的情况,因为多个类实例将共享静态类成员和静态成员函数,这就导致静态指针指向最后创建的类实例。为了避免这种情况,可以使用回调函数的一个参数来传递this指针)。
发布了38 篇原创文章 · 获赞 2 · 访问量 1530

猜你喜欢

转载自blog.csdn.net/qq_34754747/article/details/103831588