回调函数的理解与具体使用过程(用纯虚函数做回调函数)
回调函数的作用在大部分CSDN的博客中都被提到:回调函数是一种将代码作为参数传递给其他函数,并在特定事件发生后被调用的编程模式。它在异步编程中非常常见,用于处理事件处理,定时器,网络请求等;
csdn上大部分有关回调函数的实例都是调用的函数指针,而函数指针用的比较多的场景一般是在dll里面,主要步骤是:
- dll里面建立相关函数指针
- 主函数写入回调函数
- 主函数将回调函数赋值给dll的指针;
- dll中调用指针
如果回调函数不太多的话,倒还好,当回调函数有很多时,也需要定义实现很多带参回调函数的“调用函数”,在“调用函数”的传参部分有一长串,往往看着很不方便。于是近期我在上一篇博客实现计算器中,采用了不同的方式,实现了计算器将运算过程及结果式子插入数据库的回调函数。
首先在计算器的计算类中定义一个连接类ImplementCalculatorSink,方便主要实现函数与计算器类函数之间的回调,同时在对象内声明一个纯虚函数DoInsertCalFigureCallBack(string s_inFix, string s_stdInfix, string s_postFix, double d_calResult).
class ImplementCalculatorSink
{
public:
virtual void DoInsertCalFigureCallBack(string s_inFix, string s_stdInfix, string s_postFix, double d_calResult) = 0;//回调
};
然后再在主要函数CalculatorDemo头文件中使CalculatorDemo类继承连接类,同时声明一个同样的虚函数DoInsertCalFigureCallBack(string s_inFix, string s_stdInfix, string s_postFix, double d_calResult).下面代码仅放了部分;
class CalculatorDemo : public QWidget, public ImplementCalculatorSink,public ICalculatorWidgetSink
{
Q_OBJECT
public:
CalculatorDemo(QWidget *parent = nullptr);
~CalculatorDemo();
public slots:
void OnBtnDelete();//退格
void OnBtnClear();//清0
void OnBtnEqual();//得出结果
public:
virtual void DoInsertCalFigureCallBack(string s_inFix, string s_stdInfix, string s_postFix, double d_calResult);//回调
};
最后再到CalculatorDemo.cpp中去实现函数DoInsertCalFigureCallBack(string s_inFix, string s_stdInfix, string s_postFix, double d_calResult);
void CalculatorDemo::DoInsertCalFigureCallBack(string s_inFix, string s_stdInfix, string s_postFix, double d_calResult) {
m_inFix = s_inFix;
m_stdInfix = s_stdInfix;
m_postFix = s_postFix;
m_calResults = d_calResult;
if (m_pCalStorageFigure)
m_pCalStorageFigure->InsertCalFigure(m_inFix, m_stdInfix, m_postFix, m_calResults);
}
此时到最后一步,如何去实现回调?仅需要在计算类InplementCalculator.h头文件中去声明一个连接对象指针ImplementCalculatorSink* m_pImplementCalculatorSink;再在计算类InplementCalculator.cpp文件中去使用回调函数。
string ImplementCalculator::OnEqualValue(string infix) {
m_Infix = infix;
m_StdInfix =GetFormat(infix);
m_calPostfix = GetPostfix();
CalculateMethod(infix);
m_dResult = GetResult();
std::string strTempResult = std::to_string(m_dResult);
//实现回调
if (m_pImplementCalculatorSink)
m_pImplementCalculatorSink->DoInsertCalFigureCallBack(m_Infix, m_StdInfix, m_calPostfix, m_dResult);
return strTempResult;
}
虽然看起来比较绕,但是核心过程还是在一个类的函数中去实现回调函数,再在另一个类的函数去回调实现的回调函数,中间搭建起的桥梁就是声明的连接类;