回调函数实现消息通知,例如交派一个任务给某人去做,然后不去管他怎样做,什么时候做,做得怎样,而等他完成后自己汇报。这就是我对回调的理解,当然其中还有涉及了异步处理的思想;首先是函数A去调用一个函数B(相当于给人指派任务),B函数的生命周期不可知,函数A无需等待它完成而可以去处理其它的任务;那么当B函数完成了(或者需要反馈信息)时,如何返回?因为函数A没有在等待B返回,已经去处理别的任务。这个时候就需要函数B主动去调用别的函数C来实现信息的返回,这里的C函数与A函数是共享资源的,例如共同拥有一个文本框资源,那么C函数就可以改变文本框的输出。关键的地方是,A函数调用B函数时需要把C函数传给B函数,相当于A告诉B,C是我的接口人,有问题找C就行。当然,什么时候找C是由B决定的。
回调函数其实就是把一个函数的指针作为参数传送出去,它的目的是为了让被调函数根据需求来调用这个传递下去的函数。在程序开发中,有些代码往往是不允许被修改的,例如一些库文件,如果想增加一些功能或者增加一些处理,那么就可以通过回调函数来实现,因为该函数的代码实现是可以自由编写的。当然,库文件里面要预留有这种回调的接口。
其中,消息通知是回调中的一种。一般回调函数都是全局函数,由于C++类的封装性,要访问类成员需先实例对象,或者类成员定义成static属性,又或者定义回调函数为类的友元函数。要在C++中实现消息通知,那就必须能对类的成员进行访问,所以最好是用类的成员函数作为回调函数。可是,类的成员函数隐含了该类的属性,回调函数只能定义成static属性才能使用,但static属性的函数只能访问static属性的函数及变量,那就无法达到随意访问类成员的效果。经过反复了解及验证,暂时较好的实现方式是传递this指针,这样可以所操作的对象是相同的,那么资源就是相同的。
第一次写博客,作为技术菜鸟知识面不够宽,错漏的地方将不断修正!
//ClassA.h文件
#pragma once
#include "ClassB.h"
class ClassA
{
public:
ClassA();
~ClassA();
int nStart();
int nCallBack(char *p);
private:
ClassB *myClassB;
public:
char *ch;
};
//ClassA.cpp文件
#include "stdafx.h"
#include "ClassA.h"
ClassA::ClassA()
{
myClassB = new ClassB();
ch = "abc";
nStart();
}
ClassA::~ClassA()
{
if (myClassB != NULL)
{
delete myClassB;
myClassB = NULL;
}
}
int ClassA::nStart()
{
printf_s("I'm nStart\n");
myClassB->nCall(this, ch);
return 0;
}
int ClassA::nCallBack(char *p)
{
printf_s("I'm nCallBack\n");
printf_s(ch);
printf_s(p);
return 0;
}
//ClassB.h文件
#pragma once
#include
#include
class ClassA;
class ClassB
{
public:
ClassB();
~ClassB();
int nCall(ClassA *myClassA, char *p);
static unsigned int WINAPI sThread(LPVOID lpParam);
private:
HANDLE hdl;
};
//ClassB.cpp文件
#include "stdafx.h"
#include "ClassB.h"
#include "ClassA.h"
ClassA *classA;
char ch[10];
ClassB::ClassB()
{
}
ClassB::~ClassB()
{
}
int ClassB::nCall(ClassA *myClassA, char *p)
{
strcpy_s(ch, p);
hdl = (HANDLE)_beginthreadex(NULL, 0, sThread, NULL, 0, NULL);
WaitForSingleObject(hdl, INFINITE);//等待处理线程结束后调用回调函数返回通知;
classA = (ClassA*)myClassA;
printf_s("I'm nCall\n");
classA->nCallBack(ch);
//_endthreadex();
return 0;
}
unsigned int ClassB::sThread(LPVOID lpParam)
{
int i = 0;
while (ch[i] != '\0')
{
ch[i] -=0x20;
i++;
}
getchar();
return 0;
}
//main.cpp
#include "stdafx.h"
#include "ClassA.h"
int _tmain(int argc, _TCHAR* argv[])
{
ClassA myClassA;
getchar();
return 0;
}