C++的回调函数的简单实现

来源:互联网 发布:识别蘑菇的软件 编辑:程序博客网 时间:2024/05/17 12:04
在网络消息处理中经常要用到回调机制,有的是来处理异步网络数据通信问题(摄器模式),有的是来处理订阅问题(观察者模式)。
在C/C++开发用用的很多,一下是一些简单的例子(部分例子代码不全,需自行补全)
一、C的回调函数是比较简单的,
例如: 
int myFunction(int num)
{
printf("myFunction num:%d\n",num);
return -1;
}

//定义FUNC类型是一个指向函数的指针
//params[in]为int类型
//return为int类型
typedef int (*FUNC)(int);

int _tmain(int argc, _TCHAR* argv[])
{
FUNC callback = (FUNC)&myFunction;
int num = 10;
callback(10);
return 0;
}
执行结果:myFunction num:10

二、对于C++来说如何实现回调函数呢?
1、最原始的方法我们可以在类外定义全局的函数实现回调,参数上通过传递this指针来达到处理当前对象的一些业务。
例如:

typedef bool (*FUNC1)(void* pCFunc);

bool onGetFunName(void* pCFunc)
{
if(pCFunc != NULL)
{
CFunc* fuc = (CFunc*)pCFunc;
bool ret = fuc->getName();
printf("name is:%d\n", ret);
return true;
}
return false;
}

CFunc::CFunc(void)
{
}

CFunc::~CFunc(void)
{
}

bool CFunc::getName()
{
printf("getName ");
return true;
}

bool CFunc::showName()
{
FUNC1 callback = (FUNC1)&onGetFunName;
return onGetFunName(this);
}

执行结果:getName name is:1

2、一般来说我们更想让对象之前共享一个回调函数,所以很多时候用类函数来实现回调函数,例如我们一个简单的线程测试类:

//***************************************************************//
class MyThread
{
public:
MyThread(void);
~MyThread(void);

int init();

int destory();

//定义成static的类函数,此时类函数里无法操作对象私有变量
static void* __stdcall threadBody(void* arg);
static void* __stdcall producer(void* arg);

int creatProduct();
int creatConsumer();
};

/************************************************************/
static hpr_sem g_Semaphore(0);
static hpr_mutex g_mutex;
static TaskQueMgr g_MsgQ;

MyThread::MyThread(void)
{
}

MyThread::~MyThread(void)
{
}

int MyThread::init()
{
return 0;
}

int MyThread::destory()
{
//线程结束
HPR_Thread_Exit();
return 0;
}

void* __stdcall MyThread::threadBody(void* arg)
{
//hpr_guard<hpr_mutex> m_guard(g_mutex);
int nThreadnum=*(int*)arg;

//线程挂起等待
g_Semaphore.wait();

printf("creat thread :%d true\n", nThreadnum);
if(g_MsgQ.QueryTaskNum() != 0)
{
TASKEVENT* task = g_MsgQ.PopFirstTask();
if(task == NULL)
{
printf("get task error\n");
return ((void *)0);
}

int type = task->iMsgType;
int iPriority = task->iPriority;
std::vector<int> *vec = task->iDataVec;

printf("type:%d\n", type);

if(vec != NULL)
{
for(UINT32 j=0; j<vec->size(); ++j)
{
printf("data:%d\n", vec->at(j));
}
}
}
return ((void *)0);
}

void* __stdcall MyThread::producer(void* arg)
{
//线程类实例,暂时无用
MyThread*mThread = (MyThread*)arg;
printf("creat thread producer true\n");
TASKEVENT* task = new TASKEVENT;
std::vector<int> *vec = new std::vector<int>();
for(int i=0;i<10; ++i)
vec->push_back(i);
task->iMsgType = 1;
task->iPriority = 0;
task->iDataVec = vec;
g_MsgQ.PushTask(task);

//通知处理线程
g_Semaphore.post(1);

return ((void *)0);
}

int MyThread::creatProduct()
{
//创建生产者线程
HPR_HANDLE proHandle;

proHandle = MY_Thread_Create(MyThread::producer, this, 0);
if( proHandle == NULL)
{
SH_ERROR("creat thread proHandle failed!!\n");
return -1;
}
return 0;
}

int MyThread::creatConsumer()
{
HPR_HANDLE ret[THREAD_NUM_C];

for(int i=0; i<THREAD_NUM_C; ++i)
{
ret[i] = MY_Thread_Create(MyThread::threadBody, &i, 0);
if( ret[i] == NULL)
{
SH_ERROR("creat thread %d failed!!\n", i);
}
}
//g_Semaphore.post_1();
return 0;
}

main()
//**********************************//
MyThread myThread;
myThread.init();
//
myThread.creatProduct();
//
myThread.creatConsumer();
myThread.destory();

3、有时我们仅使用成员函数也可以达到该回调效果,例如:
#include <boost/bind.hpp>   
#include <boost/function.hpp>   
#include <iostream>   
  
// 函数对象 接受一个参数,返回值类型为 void  
typedef boost::function<void(const std::string &)> callback;   
  
class A   
{   
public:   
    void print(const std::string &msg)   
    {   
        std::cout << msg << std::endl;   
    }   
};   
  
class B   
{   
public:   
    //设置回调函数对象  
    void set_callback(callback cb)   
    {   
        m_cb = cb;   
    }   
  
    //调用回调函数对象  
    void do_callback()   
    {   
        m_cb("message");   
    }   
  
private:   
    callback m_cb;   
};   
  
void regular_function(const std::string &msg)   
{   
    std::cout << msg << std::endl;   
}   
  
int main()   
{   
    A a;   
    B b;   
      
    //成员函数用于回调  
    b.set_callback(boost::bind(&A::print, &a, _1));   
    b.do_callback();   
  
    // 普通函数指针同样适用  
    b.set_callback(regular_function);   
    b.do_callback();   
    return 0;  
}

4、利用多态机制,主要是子类实现继承父虚基类的纯虚函数,参数传递是只需传入基类指针即可。

//虚基类
class IMessage
{
public:
//纯虚函数
virtual void OnResponse(std::string& msg) = 0;

public:
//虚析构
virtual ~IMessage() {}


};

class CMessage: public IMessage
{
public:
CMessage(void);
~CMessage(void);

public:
//实现基类纯虚函数
void OnResponse(std::string& msg);

};

//*************************************//
void CMessage::OnResponse(std::string& msg)
{
printf("response is:%s\n", msg.c_str());
}

//***********************************//
bool notify(IMessage* pMsg)
{
std::string msg = "receive success";
pMsg->OnResponse(msg);
return true;
}

int _tmain(int argc, _TCHAR* argv[])
{

CMessage pMsg;
notify(&pMsg);

return 0;
}

0 0