这里讲解两种方式的实现和原理,比较推荐方式2:
-
函数指针:使用了裸指针
-
类对象智能指针
一、函数指针
1、模块B要调用模块A的函数fun(),大致原理如下
-
在模块A中定义static fun()
-
模块B中定义一个registercallback的接口
-
模块A通过调用registercallback接口,把指向fun()的函数指针设置到模块B中,模块B将函数指针保存起来
-
模块B 要调用时,通过保存的函数指针调用
2、具体实现
class A 中保存class B 的对象指针。
class B想要调用classA的onCallback函数。
class A {
public:
//calssB 要调用的函数onCallback,必须是静态
//这里为什么要是静态函数:
//因为静态成员函数可以用普通函数指针来存储,普通成员函数智能用类成员函数指针来存储。在注册回调传入改函数的函数指针时只能用普通函数指针
static bool onCallback(int a, void *context) {
cout << "onCallback" << a << endl;
A* a = (A*)context; //可以通过a来调用类的非静态成员
return true;
}
//classA 注册回调函数,将onCallback的函数指针传给classB
void setCb() {
if (m_pB) {
m_pB->registerCallBack(onCallback, this);
//传入this指针的原因:
// onCallback是一个静态成员函数,不能调用类的普通成员函数和普通成员变量
//传入this指针后,就能通过this指针来调用类的普通成员函数和普通成员变量
//使用方法 A* a = (A*)contex;
}
}
//保存class B的对象指针
std::shared_ptr<B> m_pB = nullptr;
};
//定义回调函数的原型,要和calssA的被回调函数一致
typedef bool (*onCallback)(int a, void *context);
class B {
public:
onCallback m_cb;
void* m_context;
void registerCallBack(onCallback cb, void* context) {
m_cb = cb;
m_context = context;
}
void test(int a) {
if (m_cb)
m_cb(a, m_context); //通过保存的函数指针回调classA的函数
}
};
int main()
{
std::shared_ptr<A> a(new A());
std::shared_ptr<B> ptr(new B());
a->m_pB = ptr;
a->setCb();
ptr->test(1);
return 0;
}
二、类对象智能指针
1、模块B要调用模块A的函数fun(),大致原理如下
-
在模块A中保存模块B的对象指针
-
将模块A的this对象传递到模块B,并且在模块B中用weak_ptr保存起来
-
B调用A的函数时,通过保存的B的对象指针来调用。
2、具体实现
//定义类,并且在类中定义classB要调用的A的函数
//class A继承于该类,并实现该类定义的虚函数
class EventCallback {
public:
virtual void onCallback(int a) {};
};
typedef std::weak_ptr<EventCallback> EVENTCALLBACK_WEAK;
class B {
public:
//定义锁,在调用回调函数之前都要锁住,该锁在作用域结束后unlock
std::recursive_mutex m_lockCb;
//保存对象A的指针,必须用weak_ptr
//如果用shared_ptr,就会出现A中保存B的智能指针,B中也保存A的智能指针
//出现智能指针的交叉引用,会导致释放时都释放不掉,出现内存泄漏
EVENTCALLBACK_WEAK m_cb;
//将A对象指针保存下来
void registerCallBack(EVENTCALLBACK_WEAK cb) {
m_cb = cb;
}
void test(int a) {
std::lock_guard<std::recursive_mutex> autoLock(m_lockCb); //上锁
auto cb = m_cb.lock(); //lock转为shared_ptr
if (cb)
cb->onCallback(a); //回调A的函数
}
};
//继承EventCallback
//通过enable_shared_from_this来使用this智能指针
class A:public EventCallback,public std::enable_shared_from_this<A>{
public:
//class B 要调用的函数,实现的EventCallback中的虚函数
void onCallback(int a) {
cout << "onCallback" << a << endl;
}
void setCb() {
if (m_pB) {
//通过shared_frome_this来获取对象本身的指针,不能直接用this
std::weak_ptr<A> self = shared_from_this();
m_pB->registerCallBack(self); //注册回调函数
//这里也可以看出为什么要继承于EventCallback:
//因为 m_pB->registerCallBack的参数类型是EVENTCALLBACK_WEAK
//A继承了EventCallback,就能把A对象作为实参传进去
}
}
std::shared_ptr<B> m_pB = nullptr;
};
int main()
{
std::shared_ptr<A> a(new A());
std::shared_ptr<B> b(new B());
a->m_pB = b;
a->setCb();
b->test(6);
return 0;
}