C++里把类函数作为回调函数

  不知道你们有没有试过把C++类里的函数作为回调函数,有时候C++可能有这样的需求,但是C++类里的函数作为回调不能像C的函数那样直接回调(毕竟C++要对象;C和我一样,没对象,用struct做的假对象不算)。这里说一下怎么处理这种问题。

最挫的办法

  把回调函数套一个娃

#include <iostream>
using namespace std;

class Test
{
public:
	void func(int data)
	{
		cout << "data = " << data << endl;
	}
};

// 这个就是给func套娃的函数
void shell_func(Test *object, int data)
{
	object->func(data);
}

void run_callback(void (*callback) (Test *, int), Test *object, int data)
{
	callback(object, data);
}

int main()
{
	Test test;
	run_callback(shell_func, &test, 1234);
	return 0;
}

  如此这般,main里就可以通过回调的方式调用到test对象里的func函数了。通过shell_func对Test里的函数封装一把,这样就和回调C的函数一样了。但是太挫了。

逼格高一点的方法

#include <iostream>
using namespace std;

class Test
{
public:
	void func(int data)
	{
		cout << "data = " << data << endl;
	}
};

void run_callback(void (*callback) (void *, int), void *object, int data)
{
	callback(object, data);
}

int main()
{
	Test test;
	run_callback((void (*) (void *, int)) &Test::func, &test, 1234);
	return 0;
}

  和最挫的办法类似,还是需要在callback的时候传入对象。其实类似python,把对象作为类函数(或许我应该叫这个函数为方法)的第一个参数,C++也可以像python这样玩。
  这里也就是把Test::func由void (Test::*) (int)类型强制转换为void (*) (void *, int)类型,这样一来,回调函数的第一个参数就可以传对象了。

逼格高一点的同时可读性好一点的方法

#include <iostream>
using namespace std;

class Test
{
public:
	void func(int data)
	{
		cout << "data = " << data << endl;
	}
};

typedef void (*FUNC) (void *, int);

void run_callback(FUNC callback, void *object, int data)
{
	callback(object, data);
}

int main()
{
	Test test;
	run_callback((FUNC) &Test::func, &test, 1234);
	return 0;
}

  因为逼格高一点的方法里,run_callback和强制转换func的类型时,写得不够优雅,所以可以搞一个typedef,把void (*) (void *, int)类型起一个别名FUNC,这样run_callback和强制类型转换时看起来就简单多了。

回调类函数有什么用

  还是有点用的,可以写一些策略模式。比如(编译下面代码需要打开c++11选项):

#include <iostream>
#include <string>
#include <map>
using namespace std;

class Test
{
public:
	static int count;
	int index;
	Test()
	{
		index = ++count;
	}
	void func1(int data)
	{
		cout << "in test"<< index <<".func1 data = " << data << endl;
	}
	void func2(int data)
	{
		cout << "in test"<< index <<".func2 data = " << data << endl;
	}
	void func3(int data)
	{
		cout << "in test"<< index <<".func3 data = " << data << endl;
	}
};

int Test::count = 0;

typedef void (*FUNC) (void *, int);

map<string, FUNC> callback_map = {
	{"func1", (FUNC) &Test::func1},
	{"func2", (FUNC) &Test::func2},
	{"func3", (FUNC) &Test::func3}
};

int main()
{
	Test test1;
	Test test2;

	int index;
	string operation;
	int data;

	cin >> index >> operation >> data;

	Test *test = &test1;
	switch (index) {
	case 1:
		test = &test1;
		break;
	case 2:
		test = &test2;
		break;
	}

	callback_map[operation](test, data);
	return 0;
}

  如果你不知道怎么打开c++11,那也不纠结了,直接用命令行这样编译(假设你把代码命名为callback_class_func.cpp):

g++ callback_class_func.cpp -o callback_class_func -std=c++11

在这里插入图片描述
  可以在代码里减少很多if else。
  这个代码类似于一些根据用户输入或者网络交互的时候,传入是字符串,但是这个字符串就是函数命。这种时候如果情况特别多,那if可以写死人。但是用一个map映射到回调函数里,就会方便很多。,map映射,只要保证这些回调函数的形参是一样的,就可以批量处理了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值