回调函数介绍
什么是回调函数?官方解释是回调函数就是一个被作为参数传递的函数。一句话解释言简意赅,但也有点晦涩难懂,听完后依旧不知道如何使用回调函数,以及应该在什么业务场景下使用回调函数。
所谓回调,就是模块A要通过模块B的某个函数b()完成一定的功能,但是函数b()自己无法实现全部功能,需要反过头来调用模块A中的某个函数a()来完成,这个a()就是回调函数。
举个业务逻辑的例子:某个业务需求实现方式是:对象A和对象B都调用对象C的fun()方法来完成某个计算,并且fun()会将计算结果保存为txt格式;突然某天需求变更了,A需要将结果保存为Raw格式,B需要将结果保存为bmp格式。现在C的fun()函数实现无法满足业务需求,因此 A, B,C商议 这个保存结果的功能由A,B 自己实现,因为不确定以后还会有什么需求变更。
//这里假设C的fun函数实现如下功能
void C::fun()
{
calculate1();
save();//save已经不满足要求,需要根据A和B不同的需求实现不同的save()
calculate2();
}
怎么实现这个功能呢,这时候就需要回调机制了。
回调函数实现
先了解下回调函数机制:
1、定义一个函数(普通函数即可);
2、将此函数的地址注册给调用者;
3、特定的事件或条件发生时,调用者使用函数指针调用回调函数
函数指针实现回调函数
函数指针实现方式就是上述所说的将函数指针当作参数传递。
typedef int(*callbackFun)(std::string, int);
int DefaultSave(std::string s, int num)
{
printf("DefaultSave() 函数执行\n");
printf("默认保存为Txt格式。\n");
return 0;
}
class SaveObj
{
public:
SaveObj()
{
callback = DefaultSave;
}
void SetCallBack(callbackFun pFun) { callback = pFun; }
int Save()
{
callback(std::string("函数指针callback"), 0);
return 0;
}
private:
callbackFun callback;
};
class TestObj1
{
public:
void CalAlgo1() { m_SaveObj.Save(); }
void CalAlgo2()
{
m_SaveObj.SetCallBack(SaveRaw);
m_SaveObj.Save();
}
private:
static int SaveRaw(std::string, int)
{
printf("TestObj1::SaveRaw()函数执行。\n");
printf("保存为Raw格式。\n");
return 0;
}
private:
SaveObj m_SaveObj;
};
namespace test
{
int SaveRaw(std::string, int)
{
printf("TestObj2::SaveRaw()函数执行。\n");
printf("保存为bmp格式。\n");
return 0;
}
}
class TestObj2
{
public:
void CalAlgo()
{
m_SaveObj.SetCallBack(test::SaveRaw);
m_SaveObj.Save();
}
private:
SaveObj m_SaveObj;
};
int main()
{
//1. 函数指针实现回调函数
TestObj1 obj1;
obj1.CalAlgo1();
obj1.CalAlgo2();
TestObj2 obj2;
obj2.CalAlgo();
return 0;
}
bind实现回调函数
借助std::bind实现回调机制,下面只介绍类的静态成员函数和全局函数的实现机制。
typedef std::function <int(std::string, int)> funObj;
int DefaultSave(std::string s, int num)
{
printf("DefaultSave() 函数执行\n");
printf("默认保存为Txt格式。\n");
return 0;
}
class SaveObj
{
public:
SaveObj()
{
m_funObj = DefaultSave;
}
void SetCallBack(funObj pFun) { m_funObj = pFun; }
int Save()
{
m_funObj(std::string("function 对象"), 0);
return 0;
}
private:
funObj m_funObj;
};
class TestObj1
{
public:
void CalAlgo1() { m_SaveObj.Save(); }
void CalAlgo2()
{
funObj fun1 = &SaveRaw;
m_SaveObj.SetCallBack(fun1);
m_SaveObj.Save();
}
private:
static int SaveRaw(std::string, int)
{
printf("TestObj1::SaveRaw()函数执行。\n");
printf("保存为Raw格式。\n");
return 0;
}
private:
SaveObj m_SaveObj;
};
namespace test
{
int SaveRaw(std::string, int)
{
printf("TestObj2::SaveRaw()函数执行。\n");
printf("保存为bmp格式。\n");
return 0;
}
}
class TestObj2
{
public:
void CalAlgo()
{
funObj fun1 = &test::SaveRaw;
m_SaveObj.SetCallBack(fun1);
m_SaveObj.Save();
}
private:
SaveObj m_SaveObj;
};
int main()
{
//std::bind实现回调函数
//bind绑定普通函数,类成员函数,类静态成员函数
TestObj1 obj1;
obj1.CalAlgo1();
obj1.CalAlgo2();
TestObj2 obj2;
obj2.CalAlgo();
return 0;
}
目前已经实现函数指针和bind实现函数机制的方式。根据不同的业务逻辑需求选择是否使用回调函数。关于函数指针和bind的具体用法,可以参考相关博客。