C++实现回调函数

一、定义

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

回调函数机制:
1、定义一个函数(普通函数即可);
2、将此函数的地址注册给调用者;
3、特定的事件或条件发生时,调用者使用函数指针调用回调函数

实例一

#include <stdio.h>
typedef int(*callback)(int,int);

int add(int a,int b,callback p){
    return (*p)(a,b);
}

int add(int a,int b){
    return a+b;
}
int main(int argc,char *args[]){
    int res = add(4,2,add);
    printf("%d\n",res);
    return 0;
}

在这个例子中,可以看到,我们定义了一个callbak的函数指针,参数为两个int,返回值为int,通过调用函数地址来进行简单的相加运算。 

二、C++中如何将类成员函数作为回调函数使用,必须是静态方法吗?

必须是静态成员函数或者全局函数来实现回调函数。
大概原因是普通的C++成员函数都隐含了一个传递函数作为参数,即this指针,C++通过传递this指针给成员函数从而实现函数可以访问C++的数据成员。由于this指针的原因,使得一个普通成员函数作为回调函数时就会因为隐含的this指针问题使得函数参数个数不匹配,从而导致回调函数编译失败。

实例二

#include <iostream>
#include <stdio.h>
using namespace std;

typedef enum
{
	CB_MOVE = 0,    //    
	CB_COMEBACK,    //  
	CB_BUYEQUIIP,   //  
}cb_type;

typedef void(*cb_func)(void *);

class CCommu //模块类  
{
public:
	CCommu()
	{//初始化函数指针数组
		memset(func_list, 0, sizeof(cb_func) *(CB_BUYEQUIIP + 1));
		memset(func_args, 0, sizeof(void *) *(CB_BUYEQUIIP + 1));
	}

	int reg_cb(cb_type type, cb_func func, void *args = NULL)//注册回调函数   
	{
		if (type <= CB_BUYEQUIIP)
		{
			func_list[type] = func;
			func_args[type] = args;
			return 0;
		}
	}
public:
	cb_func func_list[CB_BUYEQUIIP + 1];   //函数指针数组  
	void * func_args[CB_BUYEQUIIP + 1];
};

class CGameStart
{

public:
	CGameStart();
	~CGameStart();
	void Init();
	void run();
	void Execute();

	//一些回调函数  
	void static Move(void *args);
	void static Comeback(void *args);
	void static Buyequip(void *args);

public:
	CCommu *pCommu;

};

CGameStart::CGameStart() :pCommu(NULL)
{}

void CGameStart::Init() //初始化的时候,注册回调函数   
{
	pCommu = new CCommu;
	pCommu->reg_cb(CB_MOVE, Move, this);
	pCommu->reg_cb(CB_COMEBACK, Comeback, this);
}

void CGameStart::run()
{
	Init();
}

void CGameStart::Execute()
{
	cout << "callback funciton is running" << endl;

}
CGameStart::~CGameStart()
{
	if (pCommu != NULL)
	{
		delete pCommu;
		pCommu = NULL;
	}
}

void CGameStart::Move(void *args)
{
	CGameStart *pGame = (CGameStart *)args;
	pGame->Execute();
}
void CGameStart::Comeback(void *args)
{
	//char *str = (char *)args;  
	//cout << str <<endl;  
}




int main()
{
	CGameStart *pGame = new CGameStart;
	pGame->run();
	if (pGame->pCommu->func_list[CB_MOVE] != NULL)//回调函数的触发  
	{
		pGame->pCommu->func_list[CB_MOVE](pGame->pCommu->func_args[CB_MOVE]);
	}
}

参考:

https://blog.csdn.net/yidu_fanchen/article/details/80513359

https://blog.csdn.net/yidu_fanchen/article/details/80513359

  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值