参考水平第2部分

Reference level part 2

本文关键字:2部 水平 参考      更新时间:2023-10-16

扩展到这个问题,我似乎没有提供足够的细节。

我有一个名为CallbackObject的对象,它被设计为包含一个对象实例、要调用的函数的信息以及在调用时要传递的参数。

模板<typename对象类型,typename memberFunctionPtrType,typename成员FcnArg1Type>结构回调对象1{objectType obj;memberFunctionPtr类型fcnPtr;memberFcnArg1类型arg1;回调对象1(对象类型iObj,memberFunctionPtr类型iFcnPtr,成员FcnArg1类型iArg1){obj=iObj;fcnPtr=iFcnPtr;arg1=iArg1;}void exec(){(obj.*fcnPtr)(arg1)}};

使用示例:

结构点{浮动x,y;无效打印(int numTimes){for(int i=0;i<numTimes;i++)printf("%f%f\n",x,y);}};typedef void(点::*PointPrintFcType)(int);int main(){点p;p.x=p.y=1;回调对象1<点,PointPrintFcType,int>ocall(p,&Point::打印,5);ocall.exec();}

我遇到的唯一问题是,如果objectType是指针类型,那么(obj.*fcnPtr)会失败,因为如果obj是指针,它应该真正读取( (*obj).*fcnPtr)(obj->*fcnPtr)

现在我有了一个解决方案,其中我定义了另一个回调对象类,如下所示:

模板<typename pObjectType,typename memberFunctionPtrType,typename成员FcnArg1Type>结构体CallbackPObject1{pObjectType obj;memberFunctionPtr类型fcnPtr;memberFcnArg1类型arg1;回调PObject1(pObjectType iObj,memberFunctionPtr类型iFcnPtr,成员FcnArg1类型iArg1){obj=iObj;fcnPtr=iFcnPtr;arg1=iArg1;}void exec(){(obj->*fcnPtr)(arg1)}};

但这往好里说很粗糙,往坏里说很难使用,如果其他人正在使用这段代码,如果使用的对象类型实际上是指针,他们将不得不创建不同类型的回调对象。

有办法解决这个问题吗?

这里有一个示例辅助函数,假设返回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);
}

将诸如boost::function之类的多态函数对象与诸如boost::bind之类的产生函数的函数结合使用。这是一个非常优越的解决方案-天才发生在函子产生时,而不是在调用它时,并且任何可以用正确签名调用的函数对象都可以被调用。

好的,对上一个问题应用"重载"方法,我得到

模板<typename对象类型,typename memberFunctionPtrType,typename成员FcnArg1Type>结构体CallbackObject1:公共回调{objectType obj;objectType*pObj;memberFunctionPtr类型fcnPtr;memberFcnArg1类型arg1;回调对象1(对象类型iObj,memberFunctionPtr类型iFcnPtr,成员FcnArg1类型iArg1){obj=iObj;pObj=0;fcnPtr=iFcnPtr;arg1=iArg1;}回调对象1(对象类型*iObj,memberFunctionPtr类型iFcnPtr,成员FcnArg1类型iArg1){pObj=iObj;fcnPtr=iFcnPtr;arg1=iArg1;}void exec(){if(pObj)(pObj->*fcnPtr)(arg1);其他的(obj.*fcnPtr)(arg1);}};

使用

typedef void(点::*PointPrintFcType)(int);点p;p.x=p.y=1;回调对象1<点,PointPrintFcType,int>ocall(p,&Point::打印,5);ocall.exec();回调PObject1<Point*,PointPrintFcType,int>ocallP(&p,&Point::打印,2);ocallP.exec();

它工作得还可以,但内部并不像我希望的那样干净。