【问题标题】:Reference level part 2参考水平第 2 部分
【发布时间】:2011-09-08 11:23:18
【问题描述】:

Expanding on this question,看来我没有提供足够的细节。

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

模板 结构回调对象1 { 对象类型 obj ; memberFunctionPtrType fcnPtr ; memberFcnArg1Type arg1 ; CallbackObject1(objectType iObj, memberFunctionPtrType iFcnPtr, memberFcnArg1Type iArg1 ) { obj = iobj ; fcnPtr = iFcnPtr ; arg1 = iArg1 ; } 无效的执行() { (obj.*fcnPtr)(arg1); } } ;

使用示例:

结构点 { 浮动 x,y ; 无效打印(int numTimes) { for(int i = 0 ; i ocall( p, &Point::print, 5 ); ocall.exec() ; }

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

现在我有一个解决方案,我在其中定义 另一个 CallbackObject 类,如下所示:

模板 结构回调PObject1 { pObjectType 对象; memberFunctionPtrType fcnPtr ; memberFcnArg1Type arg1 ; CallbackPObject1(pObjectType iObj, memberFunctionPtrType iFcnPtr, memberFcnArg1Type iArg1 ) { obj = iobj ; fcnPtr = iFcnPtr ; arg1 = iArg1 ; } 无效的执行() { (obj->*fcnPtr)(arg1); } } ;

但这充其量是笨拙的,最坏的情况是难以使用,如果其他人正在使用此代码,如果正在使用的对象类型实际上是一个指针,他们将不得不创建一种不同类型的回调对象。

有没有办法解决这个问题?

【问题讨论】:

  • 第一个问题中提供的任何答案都可以,包括部分专业化(您的第二个类可能是第一个类的部分专业化)和使用重载函数作为辅助函数实际执行调用。
  • 他们将如何为班级工作?
  • 完全一样。你的问题是在exec() 中很难写出表达式。如果您使用 Johannes 或我的回答,它会提供一个辅助函数,您可以使用该函数在 exec() 中编写该语句。所述辅助函数可以只是全局函数或私有成员函数。
  • 是的,exec() 很难写。我用 if 语句解决了问题,请参阅下面的答案。你还能怎么写 exec?

标签: c++ templates function-pointers


【解决方案1】:

boost::function 等多态函数对象与boost::bind 等仿函数生成函数结合使用。这些是一个非常优秀的解决方案——天才发生在生成仿函数时,而不是在调用它时,并且可以调用任何可以使用正确签名调用的函数对象。

【讨论】:

  • 我也尝试过boost::bind,它很酷,但我想这样做。对不起,如果这听起来很奇怪,但我不想使用 boost::function 来解决这个特定问题
【解决方案2】:

好的,在previous question 上应用“重载”方法我得到了

模板 struct CallbackObject1 : 公共回调 { 对象类型 obj ; 对象类型 *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 ; } 无效的执行() { 如果(pobj) (pObj->*fcnPtr)(arg1); 别的 (obj.*fcnPtr)(arg1); } } ;

使用

typedef void (Point::* PointPrintFcnType)( int ) ; 点 p ; p.x=p.y=1; CallbackObject1 ocall(p, &Point::print, 5); ocall.exec() ; CallbackPObject1 ocallP( &p, &Point::print, 2 ); ocallP.exec() ;

它工作得还不错,但里面没有我想要的那么干净。

【讨论】:

    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-01-22
      • 2015-12-22
      • 2017-11-29
      • 1970-01-01
      • 2020-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多