1、背景
有这样一个场景,常见的通讯程序中,根据不同的消息类型,调用不同的处理函数。
类似于处理登陆、退出登陆、发送消息等类型。
上古操作可能会是这样的代码:
void dealLogin()
{
// ...
std::cout << "received login info, do somthing" << std::endl;
}
void dealLogout()
{
// ...
std::cout << "received logout info, do somthing" << std::endl;
}
void recv(char* data)
{
Package* pack = (Package*)data;
if (pack->msg.type == 1) // login
{
dealLogin();
}
else if (pack->msg.type == 2) // logout
{
dealLogout();
}
// else if (...) // 大量if语句
// {
// ...
// }
}
缺点:如果type很多,那么recv()中if就会越多,且后续若想增加一个type,则在recv()中代码一定是惨不忍睹。
各种type的处理糅合到一起,耦合性很强。那么怎么来解耦,想象一下,其实消息处理函数只是与type相关,则只要能根据type找到
处理函数即可,回调可以很好地解决这个问题。
2、解决办法
在一个数组中保存type与处理函数指针,在收到消息时,从数组中找出type对应的处理函数,进行调用。
再后续增加type时,只需要写一个处理函数,并添加到数组中即可,recv()中代码不用改。
int dealLogin(const char *para)
{
// ...
std::cout << "received login info:" << para << std::endl;
return 0;
}
int dealLogout(const char *para)
{
// ...
std::cout << "received logout info:" << para << std::endl;
return 0;
}
struct MsgCmd
{
int type; // msg type
int (*func)(const char *para); // 函数指针
};
// 类型与处理函数绑定
struct MsgCmd commands[] =
{
{1, dealLogin},
{2, dealLogout},
};
void recv(char* data)
{
Package* pack = (Package*)data;
for (int i = 0; i < sizeof (commands) / sizeof (MsgCmd); i++)
{
if (pack->msg.type == commands[i].type)
{
(*commands[i].func)("123");
break;
}
}
}
结果:
若想做的更加方便,可以用宏将函数定义与添加数组这2个操作合并,在用宏定义处理函数时,自动完成添加至数组。
好了,目标已经达成,消灭了大量if else/switch case。
若对你有帮助,欢迎点赞、收藏、评论,你的支持就是我的最大动力!!!
同时,阿超为大家准备了丰富的学习资料,欢迎关注公众号“超哥学编程”,即可领取。
本文涉及工程代码,公众号回复:05CallbackFunction,即可下载。