首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++:成员函数地址(函数指针)

C++:成员函数地址(函数指针)
EN

Stack Overflow用户
提问于 2011-07-30 16:52:39
回答 5查看 1.8K关注 0票数 3

我有一个类X,它具有以下方法:

代码语言:javascript
复制
void setRxHandler(void (*h)(int));

我想向它传递一个存在于类Y实例中的成员函数。

代码语言:javascript
复制
void comm_rxHandler(int status);

我尝试了以下几点:

代码语言:javascript
复制
x.setRxHandler(comm_rxHandler) 

但是它得到了以下编译错误(我使用的是Qt):

错误:没有匹配函数调用‘X::setRxHandler(<未解析重载函数type>)’

那我该怎么做呢?

我注意到,如果我声明comm_rxHandler (类Y)为静态的,我没有错误。但我希望comm_rxHandler是一种非静态的方法。另外,我希望setRxHandler方法(类X)是通用的,而不是特定于类的。所以我不能把这个方法声明为:

代码语言:javascript
复制
setRxHandler(void (Y::*h)(int))

怎么做?你能帮我吗?

谢谢!

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2011-07-30 16:54:32

与现在一样,setRxHandler原型接受一个指向不返回任何内容并接受int的函数的指针。正如您已经注意到的,这将不适用于成员函数,因为它们不能像普通函数那样被调用(您还必须处理this指针,这意味着有一个该类的实例来调用方法)。

要使它既可用于成员函数,也可用于非特定(泛型),您必须创建一个基类,并将所有要使用setRxHandler的类与该类的派生一起使用:

代码语言:javascript
复制
class Base { ... };
class Derived : public Base { ... };

// then for the prototype
void setRxHandler(void (Base::*h)(int)) { ... }
// and you can use setRxHandler for all types that derive from Base, which gives you more control than the second option, which is:

或者使用模板:

代码语言:javascript
复制
template<typename T>
void setRxHandler(void (T::*h)(int)) { ... }

使用模板选项,您实际上无法控制与setRxHandler (不包括RTTI)一起使用哪个类,这正是您想要的。

票数 0
EN

Stack Overflow用户

发布于 2011-07-30 17:01:23

C++不支持定界方法。要通过函数指针调用成员函数,需要有两件事:类的实例和函数指针。

所以setRxHandler(void (Y::*h)(int))几乎是正确的。你必须宣布它为:

代码语言:javascript
复制
void setRxHandler(Y*, void (Y::*h)(int));

要调用setRxHandler(),需要按以下方式传递它的参数:

代码语言:javascript
复制
Y y;
setRxHandler(&y, &Y::comm_rxHandler);

setRxHandler()方法中,可以使用以下语法调用函数指针:

代码语言:javascript
复制
void setRxHandler ( Y* y, void (Y::*h)(int) )
{
    // ...
    (y->*h)(0);
    // ...
}

要使泛型化,您需要将Y参数抽象出去,但这很难实现。查看Boost.Function以获得支持此用例的现有实现,以及更多的实现。

票数 1
EN

Stack Overflow用户

发布于 2011-07-30 17:03:07

将回调更改为:

代码语言:javascript
复制
void setRxHandler(std::function(<void(int)>);

然后,您可以使用绑定:

代码语言:javascript
复制
setRxHandler( std::bind(&class_name::comm_rxHandler, obj) );

(std::functionstd::bind是新版本的C++标准的一部分。很可能您的编译器已经与它们一起出现了。如果没有,它们可能生活在命名空间std::tr1中。如果其他一切都失败了,你会在助推 (他们发明的地方-- boost::functionboost::bind)找到它们。

但是,您也可以将非成员函数或静态函数传递给setRxHandler,以及函数对象(这是std::bind的结果)。

如果您的编译器已经支持lambda函数(也是下一个标准的一部分,但已经得到了GCC和VC的最新版本的支持),那么您也可以使用其中之一:

代码语言:javascript
复制
setRxHandler( [](){obj.comm_rxHandler();} );
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6884584

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档