如果有这样子的一个场景, 程序收到一个消息id后 需要用很长的if elseif else 或者switch calse来调用对应的函数 ,那可以试试这种注册派发的模式,可以使程序更简洁 可读性更高,我用代码演示一下注册派发的思路,代码不是非常严谨 结构的定义 注册和派发接口 应该独立出来 作为一个工具使用 如果有同学能派上用场, 需要自己再进一步完善下, 好不好用评论区 周知一下哟
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
//定义函数指针类型 参数为可变参数列表
typedef int (*pFunc)(va_list valist);
//定义消息注册结构
struct FuncList{
int msg_id; //消息id
pFunc func; //消息函数
}
//定义消息id 消息id定义单独一个.h会比较好
#define TEST_MSG 1 //测试消息
#define ADD_MSG 2 //取和函数
//定义消息函数结构列表
int g_func_list_len = 0;
struct FuncList g_func_list[256];
//消息注册函数
void reg_func(int msg_id/*消息id*/, pFunc func/*消息回调函数*/){
struct FuncList tmp_func;
tmp_func.msg_id = msg_id;
tmp_func.func = func;
g_func_list[g_func_list_len++] = tmp_func;
}
//消息派发函数
void dispatch_func(int msg_id /*消息id*/, ... /*可变参数*/){
//查找消息id对应的结构key 如果确定消息id比较小 如0-255范围内 则可以g_func_list[msg_id] = func的方式 存储 避免for循环查找 提高效率
int idx = -1;
for (int i = 0; i < g_func_list_len; ++i){
if(g_func_list[i].msg_id == msg_id){
idx = i;
break;
}
}
//未查找到结果
if (idx < 0) {
printf("消息id:%d未注册\n", msg_id);
return 0;
}
//取可变参数列表
va_list valist;
/* 注:一定要传入可变参数...的前一个固定参数 va_start, 因为可变参数操作函数va_arg(ptr,type) 是根据提供的参数的内存地址+数据类型字节数偏移读取内存的宏
*/
va_start(valist, msg_id);
//传入valist 参数列表 函数里使用va_arg(valist, 数据类型) 依次取出对应参数
((pFunc)g_func_list[idx].func)(valist);
//释放内存
va_end(valist);
}
//注册和派发接口有了 写个测试用例
//依函数指针类型 定义测试函数
int test_msg_func(va_list valist){
char * name = va_arg(valist, char *);
char * test_msg = va_arg(valist, char *);
printf("name:%s test_msg:%s\n", name, test_msg);
}
//取和函数
int add_func(va_list valist){
local a = va_arg(valist, int);
local b = va_arg(valist, int);
printf("%d + %d = %d\n", a, b, a+b);
}
//主函数
int main(void){
//注册
reg(TEST_MSG, test_msg_func);
reg(ADD_MSG, add_func);
//派发
dispatch_func(TEST_MSG, "小明", "测试消息派发是否正常调用函数");
dispatch_func(ADD_MSG, 5, 10);
system("pause");
return 0;
}
C++游戏服务器开发交流群:136961182,欢迎各位朋友一起交流