之前就觉得这个回调对象很麻烦,需要在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
一分析,貌似C++也可以这么做啊,做了如下测试:
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这一系列的操作简单。。。