回调函数是指程序运行时在其他函数中被调用的函数,该函数一般来说是运行时被传进到“另外一个函数”的函数,当调用的时机到达后在”另外一个函数”中被调用。回调函数在游戏服务器中使用较为广泛,比如针对删除npc这个操作:
//封装了回调函数及其相关数据结构
struct Delete
{
set<Npc> test;
bool exec(Npc n) {//回调函数,找到需要删除的npc
if (n->can_delete()) {//如果n可被删除
test.insert(n);
}
return true;
}
};
//遍历场景上每一个npc
void execAllScene(Delete& del)
{
for (...) {
del.exec(npc);
}
}
//删除npc
void realDelete(Delete& del)
{
....
}
Delete del;
scene->execAllScene(del,...);
scene->realDelete(del,...);
这样一来,把定义的Delete对象del传进一个遍历场景上的npc操作的函数execAllScene中,然后在该execAllScene中调用exec即可把场景上可删除的npc加入 待删除npc-set容器中。再把对象del传入另外一个函数realDelete中,即可完成对npc的删除操作。
这一类的应用一般写法如下:
第一种写法:
struct TestCallBack
{
TestCallBack(){}
virtual void exec(...){return ;}
};
struct MyCallBack : public TestCallBack
{
MyCallBack(){}
void exec(...) {
...//执行某种操作
}
};
void exec_every(TestCallBack& call)
{
call.exec(...);//针对一种参数执行exec
call.exec(...);//针对另外一种参数执行exec
...
}
MyCallBack cb;
exec_every(b);
其实上述代码这样写可能看起来更加容易理解:
第二种写法:
void exec()
{
...//执行某种操作
}
void exec_every()//直接遍历所有的参数类型
{
exec(...);//针对一种参数执行exec
exec(...);//针对另外一种参数执行exec
...
}
exec_every();
对比两种写法,可以发现前一种方法是对后一种方法进行了封装,更加符合面向对象的思维方式,而后一种方法更加直观容易理解。
参考资料: