C++:成员函数地址(函数指针)
我有一个类X,它有这个方法:
void setRxHandler(void (*h)(int));
我想向它传递一个存在于类Y实例中的成员函数。
void comm_rxHandler(int status);
我尝试了以下操作:
x.setRxHandler(comm_rxHandler)
但出现以下编译错误(我使用的是 Qt):
错误:没有可调用的匹配函数 'X::setRxHandler(<未解析的重载函数类型>)'
那么,我该怎么做呢?
我注意到如果我将 comm_rxHandler (Y 类)声明为静态,我就没有错误。但我希望 comm_rxHandler 作为非静态方法。另外,我希望 setRxHandler 方法(X 类)是通用的,而不是特定于类的。所以我不能将该方法声明为:
setRxHandler(void (Y::*h)(int))
如何做到这一点?你能帮我解决这个问题吗?
谢谢!
I have a class X which has this method:
void setRxHandler(void (*h)(int));
And I want to pass to it a member function that exists in instances of class Y.
void comm_rxHandler(int status);
I tried the following:
x.setRxHandler(comm_rxHandler)
But it get the following compile error (I'm using Qt):
error: no matching function for call to
‘X::setRxHandler(< unresolved overloaded function type>)’
So, how can I do that?
I noticed if I declare comm_rxHandler (class Y) as static, I have no errors. But I want comm_rxHandler as a non-static method. Also I want setRxHandler method (class X) to be generic and not class-specific. So I can't declare that method as:
setRxHandler(void (Y::*h)(int))
How to do that? Can you help me on this?
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
C++ 不支持绑定方法。要通过函数指针调用成员函数,您需要有两件事:类的实例和函数指针。
所以 setRxHandler(void (Y::*h)(int)) 几乎是正确的。您需要将其声明为:
要调用
setRxHandler()
,您需要按如下方式传递参数:在
setRxHandler()
方法中,您可以使用以下命令调用函数指针这种语法:为了实现通用,您需要将
Y
参数抽象出来,但这很难做到正确。查看 Boost.Function 以获取支持的现有实现这个用例以及更多。C++ doesn't support bound methods. To invoke a member function through a function pointer, you need to have two things: an instance of the class and the function pointer.
So
setRxHandler(void (Y::*h)(int))
is almost correct. You need to declare it as:To invoke
setRxHandler()
, you need to pass it arguments as follows:In the
setRxHandler()
method, you can invoke the function pointer using this syntax:To make generic, you need to abstract the
Y
parameter away, but this is difficult to get right. Check out Boost.Function for an existing implementation that supports this use case, and many more.将您的回调更改为:
然后您可以使用绑定器:(
std::function
和std::bind
是即将推出的下一版本 C++ 标准的一部分。可能您的编译器已经附带了它们。如果没有,它们可能位于命名空间std::tr1
中,如果其他方法都失败,您将在 boost - 这就是它们被发明的地方 - 作为boost::function
和boost::bind
。)但是,您可以,还将非成员或静态函数以及函数对象(这是
std::bind
的结果)传递给 setRxHandler。如果您的编译器已经支持 lambda 函数(也是下一个标准的一部分,但已经被最新版本的 GCC 和 VC 支持),您还可以使用其中之一:
Change your callback to this:
Then you can use binders:
(
std::function
andstd::bind
are part of the upcomming next version of the C++ standard. It's quite likely your compiler already comes with them. If not, they might live in namespacestd::tr1
. If all else fails, you will find them at boost - which is where they were invented - asboost::function
andboost::bind
.)You can, however, also pass non-member or static functions to
setRxHandler
, as well as function objects (which is the result ofstd::bind
).If your compiler already supports lambda functions (also part of the next standard, but already supported by, e.g., recent versions of GCC and VC), you can also use one of those:
现在,
setRxHandler
原型采用一个指向函数的指针,该函数不返回任何内容并采用int
。正如您所注意到的,这不适用于成员函数,因为它们不能像普通函数一样被调用(您还必须处理this
指针,这意味着拥有该类的实例来调用该方法)。为了使其能够与成员函数和非特定函数(通用)一起使用,您必须创建一个基类,并拥有要使用
setRxHandler
派生的所有类该类:或使用模板:
使用模板选项,您实际上无法控制 setRxHandler 将使用哪个类(不包括 RTTI),这可能正是您想要的。
As it is now, the
setRxHandler
prototype takes a pointer to a function that doesn't return anything and takes anint
. As you have noticed, this won't work with member functions because they can't be called like a normal function (you have to handle thethis
pointer as well, which means having an instance of that class to call the method on).To make it both work with member functions and non-specific (generic), you have to either make a base class and have all classes you want to use
setRxHandler
with derive from that class:or use templates:
With the template option, you really have no control over what class will be used with
setRxHandler
(excluding RTTI), which can be exactly what you want.您可以为
Y
创建一个基类并使用它(以避免“特定于类”),或者使用模板:但这可能会引发如何使用成员函数的问题(您告诉我们如果是的话)。
You can either make a base class for
Y
and use that (to avoid being "class specific"), or use templates:But then this may raise questions of how to use the member function (you tell us if it does).
正如其他人已经提到的,C++ 不提供此功能。
您可以使用的另一个选项是 libsigc++ ,它在 gtkmm 中广泛使用,请参阅 这个示例在他们的教程中,例如如何将指针传递给成员函数。您的示例可能类似于:
As others have already mentioned, C++ does not provide this functionality.
Another option you could use is libsigc++ which is widely used in gtkmm, see this example in their tutorial for instance on how to pass pointers to member-functions. Your example could look something like: