C++ 参考等级第2部分

C++ 参考等级第2部分,c++,templates,function-pointers,C++,Templates,Function Pointers,,看起来我没有提供足够的细节 我有一个名为CallbackObject的对象,它被设计为包含一个对象实例、要调用的函数的信息以及在调用时要传递的参数 template <typename objectType, typename memberFunctionPtrType, typename memberFcnArg1Type> struct CallbackObject1 { objectType obj ; memberFuncti

,看起来我没有提供足够的细节

我有一个名为
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 ) ; } } ; 但这充其量是粗糙的,最坏情况下是难以使用的,如果其他人正在使用此代码,那么如果使用的对象类型实际上是指针,他们将不得不创建不同类型的回调对象


有什么办法可以解决这个问题吗?

将多态函数对象(如
boost::function
)与生成函数(如
boost::bind
)结合使用。这是一个非常优秀的解决方案——天才发生在生成函子时,而不是调用函子时,任何可以使用正确签名调用的函数对象都可以被调用。

好的,在I get上应用“重载”方法

模板 结构CallbackObject1:公共回调 { 对象类型obj; objectType*pObj; memberFunctionPtrType fcnPtr; 成员Fcnarg1类型arg1; CallbackObject1(对象类型iObj, memberFunctionPtrType iFcnPtr, 成员FCNARG1类型(iArg1) { obj=iObj; pObj=0; fcnPtr=iFcnPtr; arg1=iArg1; } CallbackObject1(对象类型*iObj, memberFunctionPtrType iFcnPtr, 成员FCNARG1类型(iArg1) { pObj=iObj; fcnPtr=iFcnPtr; arg1=iArg1; } void exec() { if(pObj) (pObj->*fcnPtr)(arg1); 其他的 (obj.*fcnPtr)(arg1); } } ; 使用 typedef void(点::*PointPrintFcnType)(int); p点; p、 x=p.y=1; CallbackObject1 ocall(p,&Point::print,5); ocall.exec(); CallbackPObject1 ocallP(&p,&Point::print,2); ocallP.exec();
它工作正常,但内部不像我希望的那样干净。

下面是一个示例帮助函数,假设为void return,一个参数,并且不需要处理多个间接级别:

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);
}

第一个问题中提供的任何答案都是有效的,包括部分专门化(您的第二个类可能是第一个类的部分专门化)和使用重载函数作为帮助函数来实际执行调用。它们对类如何工作?完全相同。您的问题是很难在
exec()
中编写表达式。如果您使用Johannes或my answer,它提供了一个helper函数,您可以使用该函数在
exec()
中编写该语句。所说的helper函数可以是全局函数或私有成员函数。是的,编写exec()很困难。我写了一个if语句,见下面我的答案。你还能写exec吗?我也试过了
boost::bind
,它很酷,但我想这样做。如果这听起来像强迫症,很抱歉,但我不想使用boost::function来解决这个特定的问题 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 ) ; } } ; 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() ;
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);
}
void exec()
{
    invoke(obj, fcnPtr, arg1);
}