之前就觉得这个回调对象很麻烦,需要在create的时候,就把参数设置进去,然后execute的时候,只是直接用开始设定的参数调用这个函数。要更改,只能获取这个对象,然后用setObject来做,设置完了再execute。
而现在做lua,发现有这么一种神奇的做法:
function MessageCenter:send(message , ...) if self.handlers[message] ~= nil then for k,v in pairs(self.handlers[message]) do self:onMsg(k,v, ... ) end end end
function MessageCenter:onMsg(target,callback , ...) callback(target, ...) end
class base { public: int tag; }; typedef void (base::*SEL_CallFunc)(int id , ...); #define CALLFUNC_SELECTOR(_SELECTOR) static_cast<SEL_CallFunc>(&_SELECTOR) class callfunc { public: base* target; SEL_CallFunc func; void execute(int id, ...) { base* tmp = nullptr; va_list argList; va_start(argList,id); while(1) { tmp = va_arg(argList,base*); if(tmp!=nullptr) { (target->*func)(id,tmp,nullptr); } else { break; } } va_end(argList); } }; class child : public base { public: void testFunc(int id , ...) { base* tmp = nullptr; va_list argList; va_start(argList,id); while(1) { tmp = va_arg(argList,base*); if(tmp!=nullptr) { cout<<"id : "<<id<<" base tag : "<<tmp->tag<<endl; } else { break; } } va_end(argList); } }; int main(int argc, const char * argv[]) { child *c = new child; callfunc *cf = new callfunc; cf->target = c; cf->func = CALLFUNC_SELECTOR(child::testFunc); base *iNode = new base; iNode->tag = 1989; cf->execute(2,iNode,nullptr); return 0; }
说明可以实现。
然后开始想,为什么之前C++不这样做呢。。。
想来想去,发现:
1、C++的强类型,支持动态特性有限,导致接收的变参类型不一致的时候,很麻烦。
2、类成员函数还要做静态转型,才能完成这样的封装(当然引擎里面一直是这么做的。。。)
3、这样好像也不比之前的setObject这一系列的操作简单。。。