参考级别第 2 部分

发布于 2024-11-14 06:48:46 字数 1918 浏览 2 评论 0原文

扩展这个问题,看起来像我没有提供足够的细节。

我有一个名为 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).*fcnPtr)(obj->*fcnPtr) 如果 obj 是指针。

现在我有一个解决方案,我定义 另一个 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 ) ;
  }
} ;

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

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

Expanding on this question, it looks like I did not provide enough detail.

I have an object called CallbackObject that is designed to contain an object instance, and the information of what function to invoke, and the parameters to pass at invokation time.

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

Example of use:

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

The only problem I'm having is if objectType is a pointer type, then (obj.*fcnPtr) fails, since it should really read ( (*obj).*fcnPtr) or (obj->*fcnPtr) if obj is a pointer.

Now I have one solution, where I define another CallbackObject class like so:

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

But this is crufty at best, and difficult to use at worst, if someone else is using this code, they will have to create a different kind of Callback object if the object type being used is actually a pointer.

Is there any way around this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

千纸鹤 2024-11-21 06:48:46

下面是一个辅助函数示例,假设 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);
}

Here's an example helper function, assuming void return, one argument, and no need to handle more than one level of indirection:

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

If you need to handle more than one level of indirection, you can replace the second function with this:

template <typename T, typename F, typename A>
inline void invoke(T* obj, F func, const A& arg)
{
    invoke(*obj, func, arg);
}

This will recursively strip off levels of indirection until you end up with something that you can invoke your member function on.

You can then write your exec() function like so:

void exec()
{
    invoke(obj, fcnPtr, arg1);
}
随波逐流 2024-11-21 06:48:46

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

Use a polymorphic function object such as boost::function in combination with functor-producing functions like boost::bind. These are a far superior solution- the genius happens when the functor is produced, not when it's called, and any function object that can be called with the correct signature may be called.

小忆控 2024-11-21 06:48:46

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

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

它工作相当不错,但它的内部并不像我想要的那么干净。

Ok, applying the "overload" approach on the previous question I get

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

Use

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

It works reasonably ok, but its not as clean inside as I would like.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文