昨天看到有人在问这个问题(170分的报酬),开始感觉把不同函数存储在一个地方很简单,用void*指针数组就可以了,后来才发现却很棘手,因为要动态调用void*指针函数,编译器必须要知道函数的具体类型.埋头搞了1个小时终于写了一个比较简单类可以解决这类问题.可是问题已经关闭了.170分泡汤了.不甘心,把这个类分享给大家吧.#includeiostream#includemap#includevectorusingnamespacestd;classFuncSet{private:mapvoid*,intm_funMap;vectorvoid*m_vecFunc;void*m_pFunc;public:voidAddFuncPtr(void*pFunc,intnumParams){m_funMap.insert(mapvoid*,int::value_type(pFunc,numParams));m_vecFunc.push_back(pFunc);}unsignedintoperator()(...){void*pFunc=m_pFunc;intnNumParams=m_funMap[pFunc];intnOffset=nNumParams*4;unsignedintnRet=0;__asm{movecx,nNumParamsmovesi,ebpaddesi,8addesi,nOffsetL1:push[esi]subesi,4loopL1callpFuncmovnRet,eaxmovecx,nNumParamsL2:popeaxloopL2}returnnRet;}FuncSetreturn*this;}FuncSet=m_vecFunc.size())throwruntime_error(\"索引越界\");m_pFunc=m_vecFunc;return*this;}};intriver(intlength,intwidth){cout\"riverlength=\"length\"\\t\"\"riverwidth=\"widthendl;return13;}char*prnt(char*pstr){coutpstrendl;return\"Thequickbrownfoxjumpsoverthelazydog\";}intintplus(inti,intj,intk){returnijk;}intmain(){FuncSetfs;void*p[]={river,prnt,intplus};void*q=p[2];fs.AddFuncPtr(river,2);//加入函数指针,指明要函数接受的参数的数量fs.AddFuncPtr(prnt,1);//通过函数名字加入fs.AddFuncPtr(q,3);//通过void*指针加入coutfs[river](20,10)endl;//通过函数名索引输出\"riverlength=20,riverwidth=10\"coutfs[q](10,20,30)endl;//通过void*指针索引输出102030=60coutfs[2](30,15,21)endl;//通过下标索引输出301521=66q=prnt;cout(char*)fs[q](\"Theromanisn\'tburntinaday\")endl;//输出\"Theromanisn\'tburntinaday\"}FuncSet可以保存一大堆不同返回类型,不同形参数目的函数,并且可以在运行的时候,动态的调用,只要提供函数名或者void*指针,或者一个索引就可调用.很灵活,但因为编译器不支持这种行为,所以也不会对其检查.可靠性只能靠写代码的人了。代码比较凌乱,用得着的朋友可以自己整理下.FuncSet类在VS2008XP测试通过.
|