Expanding on this question,看起来我没有提供足够的细节。
我有一个名为CallbackObject
的对象,它被设计为包含一个对象实例,以及要调用的函数的信息,以及在调用时传递的参数。
template <typename objectType, typename memberFunctionPtrType, typename memberFcnArg1Type> struct CallbackObject1 { objectType obj ; memberFunctionPtrType fcnPtr ; memberFcnArg1Type arg1 ; CallbackObject1(objectType iObj, memberFunctionPtrType iFcnPtr, memberFcnArg1Type iArg1 ) { obj = iObj ; fcnPtr = iFcnPtr ; arg1 = iArg1 ; } void exec() { (obj.*fcnPtr)( arg1 ) ; } } ;
struct Point { float x,y ; void print( int numTimes ) { for( int i = 0 ; i < numTimes ; i++ ) printf( "%f %f\n", x, y ) ; } } ; typedef void (Point::* PointPrintFcnType)( int ) ; int main() { Point p ; p.x=p.y=1; CallbackObject1<Point, PointPrintFcnType, int> ocall( p, &Point::print, 5 ); ocall.exec() ; }
我遇到的唯一问题是如果objectType
是指针类型,那么(obj.*fcnPtr)
会失败,因为如果obj是a,它应该真正读取( (*obj).*fcnPtr)
或(obj->*fcnPtr)
指针。
现在我有一个解决方案,我在其中定义另一个 CallbackObject类,如下所示:
template <typename pObjectType, typename memberFunctionPtrType, typename memberFcnArg1Type> struct CallbackPObject1 { pObjectType obj ; memberFunctionPtrType fcnPtr ; memberFcnArg1Type arg1 ; CallbackPObject1(pObjectType iObj, memberFunctionPtrType iFcnPtr, memberFcnArg1Type iArg1 ) { obj = iObj ; fcnPtr = iFcnPtr ; arg1 = iArg1 ; } void exec() { (obj->*fcnPtr)( arg1 ) ; } } ;
但这充其量是苛刻的,并且在最坏的情况下难以使用,如果其他人正在使用此代码,如果使用的对象类型实际上是指针,则必须创建不同类型的Callback对象。
有什么方法吗?
答案 0 :(得分:1)
这是一个示例辅助函数,假设返回void,一个参数,并且不需要处理多个间接级别:
template <typename T, typename F, typename A>
inline void invoke(T& obj, F func, const A& arg)
{
(obj.*func)(arg);
}
template <typename T, typename F, typename A>
inline void invoke(T* obj, F func, const A& arg)
{
(obj->*func)(arg);
}
如果您需要处理多个间接级别,可以用以下代码替换第二个函数:
template <typename T, typename F, typename A>
inline void invoke(T* obj, F func, const A& arg)
{
invoke(*obj, func, arg);
}
这将以递归方式剥离间接级别,直到您最终得到可以调用成员函数的内容。
然后您可以像这样编写exec()
函数:
void exec()
{
invoke(obj, fcnPtr, arg1);
}
答案 1 :(得分:0)
将多态函数对象(如boost::function
)与函数生成函数(如boost::bind
)结合使用。这是一个非常优越的解决方案 - 天赋在生成仿函数时发生,而不是在调用时发生,并且可以调用任何可以使用正确签名调用的函数对象。
答案 2 :(得分:0)
好的,在我previous question
上应用“重载”方法template <typename objectType, typename memberFunctionPtrType, typename memberFcnArg1Type> struct CallbackObject1 : public Callback { objectType obj ; objectType *pObj ; memberFunctionPtrType fcnPtr ; memberFcnArg1Type arg1 ; CallbackObject1(objectType iObj, memberFunctionPtrType iFcnPtr, memberFcnArg1Type iArg1 ) { obj = iObj ; pObj = 0 ; fcnPtr = iFcnPtr ; arg1 = iArg1 ; } CallbackObject1(objectType *iObj, memberFunctionPtrType iFcnPtr, memberFcnArg1Type iArg1 ) { pObj = iObj ; fcnPtr = iFcnPtr ; arg1 = iArg1 ; } void exec() { if( pObj ) (pObj->*fcnPtr)( arg1 ) ; else (obj.*fcnPtr)( arg1 ) ; } } ;
typedef void (Point::* PointPrintFcnType)( int ) ; Point p ; p.x=p.y=1; CallbackObject1<Point, PointPrintFcnType, int> ocall( p, &Point::print, 5 ); ocall.exec() ; CallbackPObject1<Point*, PointPrintFcnType, int> ocallP( &p, &Point::print, 2 ); ocallP.exec() ;
它的工作原理相当不错,但它并不像我想的那样干净。