1). 不使用成员函数,直接使用普通C函数,为了实现在C函数中可以访问类的成员变量,可以使用友元操作符(friend),在C++中将该C函数说明为类的友元即可。这种处理机制与普通的C编程中使用回调函数一样。
2). 使用静态成员函数,静态成员函数不使用this指针作为隐含参数,这样就可以作为回调函数了。静态成员函数具有两大特点:其一,可以在没有类实例的情况下使用;其二,只能访问静态成员变量和静态成员函数,不能访问非静态成员变量和非静态成员函数。由于在C++中使用类成员函数作为回调函数的目的就是为了访问所有的成员变量和成员函数,如果作不到这一点将不具有实际意义。解决的办法也很简单,就是使用一个静态类指针作为类成员,通过在类创建时初始化该静态指针,如pThis=this,然后在回调函数中通过该静态指针就可以访问所有成员变量和成员函数了。这种处理办法适用于只有一个类实例的情况,因为多个类实例将共享静态类成员和静态成员函数,这就导致静态指针指向最后创建的类实例。为了避免这种情况,可以使用回调函数的一个参数来传递this指针,从而实现数据成员共享。这种方法比较麻烦。
简单的c语言回调函数
-
/*
-
* main.cc
-
*
-
* Created on: 2011-12-1
-
* Author: simondu
-
*/
-
-
#include "head.h"
-
//#include "test5.cc"
-
-
using namespace std;
-
typedef int (*Fn)(char *p);
-
int callbackfn(Fn fn ,char *p)
-
{
-
-
fn(p);
-
}
-
int callbackfn2(int(*ptr)(char* p), char* str)
-
{
-
(*ptr)(str);
-
-
}
-
int Afun(char *p)
-
{
-
printf("%s\n",p);
-
return 0;
-
}
-
-
int main(int argc, char* argv[])
-
{
-
printf("Starting...... \n");
-
char *str = "hello world";
-
callbackfn(Afun,str);
-
callbackfn2(Afun,str);
-
printf("Ending...... \n");
-
return 0;
-
}
c++ 写的一个简单的回调函数
-
/*
-
* main.cc
-
*
-
* Created on: 2011-12-1
-
* Author: simondu
-
*/
-
-
#include "head.h"
-
-
-
class CTest;
-
typedef void (CTest::*DoMessageFunc)(char* msg, int msgid );
-
class CTest
-
{
-
public:
-
CTest(){}
-
~CTest(){}
-
void DoMsgFunc1(char* pMsg,int nID)
-
{
-
printf("%s\n",pMsg);
-
printf("回调函数\n");
-
}
-
-
void RegiestMsg(int nSrcID,DoMessageFunc pFunc)
-
{
-
m_pFunc = pFunc;
-
}
-
-
void HandleMessage(int nMsgID, char* pMsg, int nID)
-
{
-
(this->*m_pFunc)(pMsg,nID);
-
}
-
private:
-
DoMessageFunc m_pFunc;
-
};
-
-
using namespace std;
-
-
-
int main(int argc, char* argv[])
-
{
-
printf("Starting...... \n");
-
CTest obj ;
-
obj.RegiestMsg(12,&CTest::DoMsgFunc1);
-
obj.HandleMessage(1,"test",6);
-
printf("Ending...... \n");
-
return 0;
-
}
刚刚在网上看到C++回调函数的描述非常的好
转载自
用过C++进行过面向对象程序设计的用户都知道,程序中的对象很少单独存在。不考虑对象间的相互作用几乎是不可能的。所以,标识对象间的关系或建立对象间的消息连接是面向对象程序设计的一项重要任务。本文着重从C++程序设计的角度,提出一种建立对象间消息连接的实用方法。如果你想详细了解面向对象程序设计技术,请参阅有关专著。大家都知道对象是数据和方法的封装体。在C++中,它们分别表现为数据成员和成员函数。程序设计者通过执行对象的各种方法,来改变对象的状态(即改变对象的属性数据)。从而使该对象发生某些“事件”。当一对象发生某事件时,它通常需向其它相关对象发送“消息”,请求它们作出一些处理。 这时,发生事件并向其它对象请求处理的对象被称为“事件对象”,而处理事件的对象被称为“回调对象”。回调对象对事件的处理称为“回调函数”。在C++中,这一过程相当于:当事件对象发生事件时,调用
回调对象的某些成员函数。通常的作法是回调对象向事件对象传递对象指针。但这种方法不通用。为了减少程序设计的工作量,本文提出一种建立对象间消息连接的系统方法。它的思路是:将“事件发生→请求处理→执行处理”这一过程抽象成一个“回调”(CallBack)类。通过继承,用户可以轻松获取建立对象间消息连接的机制。
一、回调类的数据结构及其成员函数
本文提出的CallBack类支持三种回调函数。它们是:回调对象中的成员函数,属于回调类的静态成员函数和普通的C函数。CallBackle类中包含一回调函数表callBackList。它用于记录事件名称,指向回调函数及回调对象的指针。该表的每一个节点为一个事件记录EventRecord。每个事件记录包含三个域:事件名指针eventName,指向回调对象的指针pointerToCBO,指向回调函数的指针pointerToCBF或pointerToCBSF(其中,pointerToCBF指向回调对象的成员函数,pointerToCBSF指向回调类的静态成员函数或普通函数。它们同处于一共用体内)。CallBack类所提供的回调机制是这样的:在事件对象上注册回调对象中的回调函数;当事件发生时,事件对象在其回调表中检索并执行回调函数。从而使二者的消息连接得以建立。(关于该类的具体实现,请参阅文后所附的程序清单)
回调对象
事件对象
事件名 回调对象指针 回调函数指针
“event” pointerCBO pointerToCBF或 pointerTOCBSF
- - - - - -
AddCallBack: 注册事件名和指向回调函数,回调对象的指针
CallCallBack: 在回调表中,检索注册在指定事件上回调函数并调用它们
事件发生时,调用CallCallBack函数对事件event进行处理的成员函数
从CallBack类继承的回调表callBackList, 成员函数AddCallBack和CallCallBack。
当回调函数为静态成员函数或普通C函数时, pointerToCBO为NULL。
事件名是回调表callBackLis中的检索关键字。
回调对象中其它成员函数
CallBack类的成员函数AddCallBack用来将回调函数注册到事件对象的回调表中。它有
两个重载版本:
-
void CallBack::AddCallBack(char *event,CallBackFunction cbf,CallBack *p);
-
void CallBack::AddCallBack(char *event,CallBackStaticFunction cbsf);
其中,第一个AddCallBack用来将某回调对象的成员函数注册到事件对象的回调表中。
第二个AddCallBack用来将或某回调类的静态成员函数注册到事件对象的回调表中。
在上参数表中,event是指向事件名字符串的指针,p是指向回调对象的指针,cbf和cbsf分别是
指向成员函数及静态成员函数(或普通函数)的指针。当回调函数来自某回调对象Some
Object时,传递成员函数指针应采用如下格式:
(CallBackFunction)&SomeObject::MemberFunctionName; 传递SomeObject类的某静态成员函数指针应采用格式:(CallBackStaticFunction)& SomeObject::FunctionName;
传递程序中普通函数指针时,只需传递函数名即可。
CallBack类的成员函数void CallBack::CallCallBack(char *ename, CallData callda
ta = NULL)用来调用注册在事件ename上的所有回调函数。其中,calldata为数据指针(
CallData实际上就是void*,详见程序清单)。事件对象可通过它向回调对象传递有用的
数据。该成员函数通常在事件对象的成员函数中调用,因为通常只有事件对象的成员函
数才能改变对象的内部数据,从而使某些事件发生。
成员函数RemoveCallback用来删除注册在事件对象上的回调函数。它的三个重载版本依
次为:
-
void CallBack::RemoveCallBack(char *event,CallBackFunction cbf,CallBack *p);
-
void CallBack::RemoveCallBack(char *event,CallBackStaticFunction cbsf);
-
void CallBack::RemoveCallBack(char *event);
其中,event,cbf,cbsf,p等参数和成员函数AddCallBack中各参数一样。第一个RemoveC
allBack用于删除注册在事件event上某回调对象的一个成员函数。第二个RemoveCallBa
ck用于删除注册在事件event上的某普通函数或某回调类的一个静态成员函数。第三个R
emoveCallBack用于删除注册在事件event上的全部回调函数。
二、CallBack类的使用方法
使用CallBack类,可按以下步骤进行:
1.确定程序中哪些对象间存在关系,需要建立消息连接。并确定在各特定消息连接关系
中,哪个对象是事件对象,哪个对象是回调对象。
2.事件对象类和回调对象类都必须从CallBack类继承,以获得回调支持。
3.为事件对象注册回调数据。包括:事件名,回调函数名,指向回调对象的指针。
4.当你感兴趣的事件发生时,在事件对象类引发事件的成员函数中调用CallCallBack函
数。
下面是一个具体的例子。通过它你会对Callback类的使用方法有进一步的了解。
-
/*
-
* callback.h
-
*
-
* Created on: 2012-1-12
-
* Author: simondu
-
*/
-
-
#ifndef CALLBACK_H_
-
#define CALLBACK_H_
-
-
#include<stdlib.h>
-
#include<string.h>
-
#include<iostream.h>
-
#define CALLBACKLIST_INIT_SIZE 10
-
#define CALLBACKLIST_INCREMENT 5
-
class CallBack;
-
typedef void *CallData;//回调数据指针类型定义
-
typedef void (CallBack::*CallBackFunction)(CallData); //指向回调成员函数的指针
-
typedef void (*CallBackStaticFunction)(CallData); //指向静态成员函数或普通函数的指针类型定义
-
-
class EventRecord{
-
private:
-
char *eventName; //回调事件名称
-
CallBack *pointerToCBO;//指向回调对象的指针
-
//指向成员函数的指针和指向静态成员函数(或普通函数)指针的共用体
-
union{
-
CallBackFunction pointerToCBF;
-
CallBackStaticFunction pointerToCBSF;
-
};
-
public:
-
EventRecord(void); //事件记录类的缺省构造函数
-
//构造包含成员函数的事件记录
-
EventRecord(char *ename,CallBack *pCBO,CallBackFunction pCBF);
-
//构造包含静态成员函数或普通函数的事件记录
-
EventRecord(char *ename,CallBackStaticFunction pCBSF);
-
~EventRecord(void);//析构事件记录
-
void operator = (const EventRecord& er);//重载赋值运算符
-
//判断当前事件记录的事件名是否为ename
-
int operator == (char *ename) const;
-
//判断当前事件记录是否和指定事件记录相等
-
int operator == (const EventRecord& er) const;
-
void Flush(void); //将当前事件记录清空
-
int IsEmpty(void) const;//判断事件记录是否为空(即事件名是否为空)
-
friend class CallBack; //让CallBack类能访问EventRecord的私有成员;
-
-
};
-
-
class CallBack {
-
private:
-
EventRecord *callBackList; //回调事件表
-
int curpos; //当前事件记录位置
-
int lastpos; //回调表中最后一空闲位置
-
int size; //回调表的大小
-
void MoveFirst(void) { curpos = 0; }//将当前记录置为第一条记录
-
void MoveNext(void) //将下一条记录置为当前记录
-
{
-
if(curpos == lastpos) return;
-
curpos++;
-
}
-
//判断回调表是否被遍历完
-
int EndOfList(void) const { return curpos == lastpos; }
-
public:
-
CallBack(void);//构造函数
-
CallBack(const CallBack& cb);//拷贝构造函数
-
~CallBack(void);//析构函数
-
void operator = (const CallBack& cb);// 重载赋值运算符
-
//将回调对象的成员函数、静态成员函数(或普通函数)
-
//注册为事件对象的回调函数
-
void AddCallBack(char *event,CallBackFunction cbf,CallBack *p);
-
void AddCallBack(char *event,CallBackStaticFunction cbsf);
-
//删除注册在指定事件上的回调函数
-
void RemoveCallBack(char *event,CallBackFunction cbf,CallBack *p);
-
void RemoveCallBack(char *event,CallBackStaticFunction cbsf);
-
void RemoveCallBack(char *event);// 删除某事件的全部记录
-
//执行注册在某一事件上的所有回调函数
-
void CallCallBack(char *event, CallData calldata = NULL);
-
};
-
-
#endif /* CALLBACK_H_ */
-
/*
-
* callback.cpp
-
*
-
* Created on: 2012-1-12
-
* Author: simondu
-
*/
-
-
#include "callback.h"
-
-
EventRecord::EventRecord(void)
-
{
-
eventName = NULL;
-
pointerToCBO = NULL;
-
//因为sizeof(CallBackFunction) > sizeof(CallBackStaticFunction)
-
pointerToCBF = NULL;
-
}
-
EventRecord::EventRecord(char *ename, CallBack *pCBO, CallBackFunction pCBF)
-
:pointerToCBO(pCBO), pointerToCBF(pCBF)
-
{
-
eventName = strdup(ename);
-
}
-
EventRecord::EventRecord(char *ename, CallBackStaticFunction pCBSF)
-
:pointerToCBO(NULL), pointerToCBSF(pCBSF)
-
{
-
eventName = strdup(ename);
-
}
-
EventRecord::~EventRecord(void)
-
{
-
if(eventName) delete eventName;
-
}
-
void EventRecord::operator = (const EventRecord& er)
-
{
-
if(er.eventName)
-
eventName = strdup(er.eventName);
-
else
-
eventName = NULL;
-
pointerToCBO = er.pointerToCBO;
-
pointerToCBF = er.pointerToCBF;
-
}
-
int EventRecord::operator == (char *ename) const
-
{
-
if((eventName == NULL)||ename == NULL)
-
return eventName == ename;
-
else
-
return strcmp(eventName,ename) == 0;
-
}
-
int EventRecord::operator == (const EventRecord& er) const
-
{
-
return (er == eventName) /*er和eventname不能交换位置*/
-
&&(pointerToCBO == er.pointerToCBO)
-
&&(pointerToCBO ?
-
(pointerToCBF == er.pointerToCBF):
-
(pointerToCBSF == er.pointerToCBSF));
-
}
-
void EventRecord::Flush(void)
-
{
-
if(eventName){
-
delete eventName;
-
eventName = NULL;
-
}
-
pointerToCBO = NULL;
-
pointerToCBF = NULL;
-
}
-
int EventRecord::IsEmpty(void) const
-
{
-
if(eventName == NULL)
-
return 1;
-
else
-
return 0;
-
}
-
//Callback类的实现
-
CallBack::CallBack(void)
-
{
-
//按初始尺寸为回调表分配内存空间
-
callBackList = new EventRecord[CALLBACKLIST_INIT_SIZE];
-
if(!callBackList){
-
cerr<<"CallBack: memory allocation error."<<endl;
-
exit(1);
-
}
-
size = CALLBACKLIST_INIT_SIZE;
-
lastpos = 0;
-
curpos = 0;
-
}
-
CallBack::CallBack(const CallBack& cb): curpos(cb.curpos),lastpos(cb.lastpos),size(cb.size)
-
{
-
callBackList = new EventRecord[size];
-
if(!callBackList){
-
cerr<<"CallBack: memory allocation error."<<endl;
-
exit(1);
-
}
-
//一一复制各条事件记录
-
for(int i = 0; i < size; i++) callBackList[i] = cb.callBackList[i];
-
}
-
void CallBack::operator = (const CallBack& cb)
-
{
-
curpos = cb.curpos;
-
lastpos = cb.lastpos;
-
size = cb.size;
-
delete [] callBackList;//删除旧的回调表
-
callBackList = new EventRecord[size];//重新分配内存空间
-
if(!callBackList){
-
cerr<<"CallBack: memory allocation error."<<endl;
-
exit(1);
-
}
-
//一一复制各条事件记录
-
for(int i = 0; i < size; i++) callBackList[i] = cb.callBackList[i];
-
}
-
CallBack::~CallBack(void)
-
{
-
delete [] callBackList;
-
}
-
void CallBack::AddCallBack(char *event, CallBackFunction pCBF, CallBack *pCBO)
-
{
-
//如事件名为空,退出
-
if( (event == NULL)?1:(strlen(event) == 0)) return;
-
//寻找因删除事件记录而产生的第一个空闲位置,并填写新事件记录
-
int start=0;
-
for(start=0; start < lastpos; start++ )
-
if(callBackList[start].IsEmpty()){
-
callBackList[start] = EventRecord(event,pCBO,pCBF);
-
break;
-
}
-
if(start < lastpos) return; //确实存在空闲位置
-
//没有空闲位置,在回调表后追加新记录
-
if(lastpos == size) //回调表已满,需“伸长”
-
{
-
EventRecord *tempList = callBackList;//暂存旧回调表指针
-
//以一定的步长“伸长”回调表
-
callBackList = new EventRecord[size + CALLBACKLIST_INCREMENT];
-
if(!callBackList){
-
cerr<<"CallBack: memory allocation error."<<endl;
-
exit(1);
-
}
-
//复制旧回调表中的记录
-
for(int i = 0; i < size; i++) callBackList[i] = tempList[i];
-
delete [] tempList;//删除旧回调表
-
size += CALLBACKLIST_INCREMENT;//记下新回调表的尺寸
-
}
-
//构造新的事件记录并将其填入回调表中
-
callBackList[lastpos] = EventRecord(event,pCBO,pCBF);
-
lastpos++;
-
}
-
void CallBack::AddCallBack(char *event,CallBackStaticFunction pCBSF)
-
{
-
if( (event == NULL)?1:(strlen(event) == 0)) return;
-
int start=0;
-
for(start = 0; start<lastpos; start++)
-
if(callBackList[start].IsEmpty()){
-
callBackList[start] = EventRecord(event,pCBSF);
-
break;
-
}
-
if(start < lastpos) return; //a hole is found
-
if(lastpos == size) //event list is insufficient
-
{
-
EventRecord *tempList = callBackList;
-
callBackList = new EventRecord[size + CALLBACKLIST_INCREMENT];
-
if(!callBackList){
-
cerr<<"CallBack: memory allocation error."<<endl;
-
exit(1);
-
}
-
for(int i = 0; i < size; i++) callBackList[i] = tempList[i];
-
delete [] tempList;
-
size += CALLBACKLIST_INCREMENT;
-
}
-
callBackList[lastpos] = EventRecord(event,pCBSF);
-
lastpos++;
-
}
-
//删除注册在指定事件上的成员函数
-
void CallBack::RemoveCallBack(char *event, CallBackFunction pCBF, CallBack *
-
pCBO)
-
{
-
if( (event == NULL)?1:(strlen(event) == 0)) return;
-
EventRecord er(event,pCBO,pCBF);
-
for(int i = 0; i < lastpos; i++)
-
if(callBackList[i] == er) callBackList[i].Flush();
-
}
-
//删除注册在指定事件上的静态成员函数或普通函数
-
void CallBack::RemoveCallBack(char *event,CallBackStaticFunction pCBSF)
-
{
-
if( (event == NULL)?1:(strlen(event) == 0)) return;
-
EventRecord er(event,pCBSF);
-
for(int i = 0; i < lastpos; i++)
-
if(callBackList[i] == er) callBackList[i].Flush();
-
}
-
//删除注册在指定事件上的所有回调函数
-
void CallBack::RemoveCallBack(char *event)
-
{
-
if( (event == NULL)?1:(strlen(event) == 0)) return;
-
for(int i = 0; i < lastpos; i++)
-
if(callBackList[i] == event) callBackList[i].Flush();
-
}
-
void CallBack::CallCallBack(char *event, CallData callData)
-
{
-
if( (event == NULL)?1:(strlen(event) == 0)) return;
-
CallBack *pCBO;
-
CallBackFunction pCBF;
-
CallBackStaticFunction pCBSF;
-
MoveFirst();
-
while(!EndOfList())
-
{
-
//如当前事件记录和指定事件不匹配,转入下一条记录继续循环
-
if(!(callBackList[curpos] == event))
-
{
-
MoveNext();
-
continue;
-
}
-
//如找到匹配记录
-
pCBO = callBackList[curpos].pointerToCBO;
-
//如事件记录中回调对象指针为空,说明该记录中保存的是静态函数指针
-
if(pCBO == NULL)
-
{
-
pCBSF = callBackList[curpos].pointerToCBSF;
-
pCBSF(callData);//调用该静态回调函数
-
}
-
else //如事件记录中回调对象指针非空,说明该记录中保存的是成员函数指针
-
{
-
pCBF = callBackList[curpos].pointerToCBF;
-
(pCBO->*pCBF)(callData);// 调用该回调对象的成员函数
-
}
-
MoveNext();
-
}
-
}
-
/*
-
* test5.cc
-
*
-
* Created on: 2012-1-11
-
* Author: simondu
-
*/
-
-
-
#include "head.h"
-
#include"callback.h"
-
class Speaker:public CallBack
-
{
-
private:
-
int volume;
-
public:
-
Speaker(int v): volume(v) {}
-
void IncreaseVolume(int v) //增加音量成员函数
-
{
-
volume += v;
-
if(volume > 20){
-
//“音量大于20”事件发生了
-
//调用注册在两事件上的回调函数
-
CallCallBack("音量改变了");
-
CallCallBack("音量大于20", &volume);
-
}
-
}
-
void DecreaseVolume(int v) //降低音量成员函数
-
{
-
volume -= v;
-
if(volume < 5){ //“音量小于5”事件发生了
-
//调用注册在两事件上的回调函数
-
CallCallBack("音量改变了");
-
CallCallBack("音量小于5", &volume);
-
}
-
}
-
};
-
//“耳朵”类
-
class Ear : public CallBack
-
{
-
public:
-
static void Response(CallData callData) //对“音量改变”的反应
-
{
-
cout<<"音量改变了."<<endl;
-
}
-
void HighVoiceResponse(CallData callData)//对高音的反应
-
{
-
cout<<"喂!太吵了!现在音量是:"<<*((int *)callData)<<endl;
-
}
-
void LowVoiceResponse(CallData callData)// 对低音的反应
-
{
-
cout<<"啊!我听不清了。现在音量是:"<<*((int *)callData)<<endl;
-
}
-
};
-
/*
-
* main.cc
-
*
-
* Created on: 2011-12-1
-
* Author: simondu
-
*/
-
-
#include "head.h"
-
#include "test5.cc"
-
-
using namespace std;
-
-
int main(int argc, char* argv[])
-
{
-
printf("Starting...... \n");
-
Speaker s(10); //现在音量为10
-
Ear e;
-
//为事件对象s注册回调函数
-
s.AddCallBack("音量大于20",(CallBackFunction)&Ear::HighVoiceResponse,&e);
-
s.AddCallBack("音量小于5",(CallBackFunction)&Ear::LowVoiceResponse,& e);
-
s.AddCallBack("音量改变了",(CallBackStaticFunction)&Ear::Response);
-
s.IncreaseVolume(12);//将音量增加12,现在音量位22
-
s.DecreaseVolume(20);//将音量减少20,现在音量位2
-
-
printf("Ending...... \n");
-
return 0;
-
}