回调函数
机制 使用了 函数指针
。
步骤:
- 1.定义一个函数指针,如
typedef void (*func_ptr)(std::string str);
- 2.定义一个 回调函数
void func(std::string str)
,需要注意的是,回调函数必须和前面定义的函数指针参数类型和参数个数一致 - 3.定义一个注册回调函数
void SetCallback(func_ptr ptr);
, 其中func_ptr
是一个函数指针类型,之后会把一个回调函数地址(函数名func
)赋值给ptr
;
1 typedef void (*func_ptr)(std::string str);
2
3 class Test{
4 func_ptr m_ptr;
5
6 void SetCallback(func_ptr ptr){
7 this->m_ptr = ptr; // 注册回调函数把传入的函数指针 ptr 赋值给了成员函数m_ptr
8 }
9 }
10
11 // 在其他地方或其他cpp文件定义一个下面这样的函数
12 void func(std::string str)
13 {
14 /*code*/
15 }
16
17 int main(){
18 Test test;
19 test.SetCallback(func);
20 }
如:SetCallback(func)
把 一个已经定义的函数func
的函数地址 赋值给 函数指针 m_ptr
,这样就相当于注册了回调函数,当我们在对象的其他位置就可以直接以函数形式调用m_ptr("Jack")
了。
所以注册回调函数SetCallback(func_ptr ptr)
的作用就是 给成员变量函数指针进行赋值,相当于对是对对象实现回调函数,以便后面直接调用该回调函数。
如果要在两个class对象之间传递数据,最简单直接的方法在一个类中定义一个全局变量,然后在另一个类里面extern这个变量,这样就等于这个全局变量同时作用于两个类对象中,这样做能暂时解决问题,然而可能会出现新的问题,比如,代码的复用性不好,全局变量会在main之前初始化,增加了程序的负担;还有一个致命的问题,如果是多线程程序,就需要加锁保证同一时刻只能有一个对象在访问修改这个全局变量,程序的效率可能会下降,当然如果定义的全局变量过多,由于加锁不慎很可能会导致死锁,致使程序奔溃,今天介绍一中很实用的办法,线程安全并且封装性好;
先看代码
1 #include <iostream>
2
3 using namespace std;
4
5 typedef void(*CallBack)(char* s);
6
7 class A{
8 public:
9 void setCbk(CallBack call_back){
10 this->_my_call_back = call_back;
11 _my_call_back("123456789");
12 }
13 public:
14 A(){}
15 ~A(){}
16 CallBack _my_call_back;
17 };
18
19 class B{
20 public:
21 static void OnCallBack(char * s){
22 cout << "gxs s:" << s << endl;
23 }
24
25 public:
26 B(){
27 A a;
28 a.setCbk(B::OnCallBack); //注册回调函数
29 }
30 ~B(){}
31 };
32
33 int main()
34 {
35 B b;
36 return 0;
37 }
首先typedef void(*CallBack)(char* s)
申明了一个函数指针,这个CallBack
指针指向一个返回值是void
类型参数是char*
的函数;那怎么才能让类A
的char*
数据传到类B来呢,读代码就知道了,很简单在类A里面定义一个CallBack
的成员变量,然后把类B
的OnCallBack
的地址赋值给A
的CallBack
,这样A
的CallBack
在执行的时候就会执行B
的OnCallBack
的代码了;
该怎么理解呢? 理解这个原理首先得理解函数指针
的含义,顾名思义,函数指针
它是一个指针
,这个指针
指向的是一个函数
。这个意思就是,你可以通过一个指针
去调用一个函数
,所以你想调用别的类的函数,就要把它类里面这个函数的地址
获取到赋值到你类里面的函数指针。
其实,这是回调函数最原始的做法,很多IDE
已经开发出非常高效便捷的回调形式,最经典的莫过于Qt
的信号槽
机制了,它做的太好了,好到你可以任意的设置回调的接口而不必关心这个谁去发起这个连接,换句话说就是: 你在Class A
中设置回调的时候class B
这个对象不存在也没关系