参考级别第 2 部分
扩展这个问题,看起来像我没有提供足够的细节。
我有一个名为 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
下面是一个辅助函数示例,假设 void 返回、一个参数,并且无需处理多于一层的间接:
如果您需要处理多于一层的间接,您可以用此替换第二个函数:
这将递归地剥离关闭间接级别,直到最终得到可以调用成员函数的东西。
然后您可以像这样编写
exec()
函数:Here's an example helper function, assuming void return, one argument, and no need to handle more than one level of indirection:
If you need to handle more than one level of indirection, you can replace the second function with this:
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:将多态函数对象(例如
boost::function
)与函子生成函数(例如boost::bind
)结合使用。这是一个远远优越的解决方案——天才发生在函子生成时,而不是调用它时,并且可以调用任何可以使用正确签名调用的函数对象。Use a polymorphic function object such as
boost::function
in combination with functor-producing functions likeboost::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.好的,对 上一个问题应用“重载”方法 我得到
使用
它工作相当不错,但它的内部并不像我想要的那么干净。
Ok, applying the "overload" approach on the previous question I get
Use
It works reasonably ok, but its not as clean inside as I would like.