我有一个类X ,它有这个方法:
void setRxHandler(void (*h)(int));
我想传递一个存在于 Y类实例中的成员函数。
void comm_rxHandler(int status);
我尝试了以下内容:
x.setRxHandler(comm_rxHandler)
但它得到以下编译错误(我正在使用Qt):
错误:没有匹配的调用函数 'X :: setRxHandler(< unresolved overloaded function type>)'
那么,我该怎么做?
我注意到如果我将comm_rxHandler(类Y)声明为静态,我没有错误。但我想将comm_rxHandler作为非静态方法。另外,我希望setRxHandler方法(类X)是通用的,而不是特定于类。所以我不能将该方法声明为:
setRxHandler(void (Y::*h)(int))
怎么做?你能帮我解决这个问题吗?
谢谢!
答案 0 :(得分:1)
C ++不支持bound methods。要通过函数指针调用成员函数,您需要有两件事:类的实例和函数指针。
所以setRxHandler(void (Y::*h)(int))
几乎是正确的。您需要将其声明为:
void setRxHandler(Y*, void (Y::*h)(int));
要调用setRxHandler()
,您需要按如下方式传递参数:
Y y;
setRxHandler(&y, &Y::comm_rxHandler);
在setRxHandler()
方法中,您可以使用以下语法调用函数指针:
void setRxHandler ( Y* y, void (Y::*h)(int) )
{
// ...
(y->*h)(0);
// ...
}
要制作通用,您需要抽象Y
参数,但这很难做到。查看Boost.Function以获取支持此用例的现有实现,以及更多内容。
答案 1 :(得分:1)
将您的回调更改为:
void setRxHandler(std::function(<void(int)>);
然后你可以使用粘合剂:
setRxHandler( std::bind(&class_name::comm_rxHandler, obj) );
(std::function
和std::bind
是升级下一版C ++标准的一部分。很可能你的编译器已经附带它们。如果没有,它们可能存在于命名空间std::tr1
中如果所有其他方法都失败了,你会在boost找到它们 - 这就是它们被发明的地方 - boost::function
和boost::bind
。)
但是,您也可以将非成员函数或静态函数传递给setRxHandler
,以及函数对象(这是std::bind
的结果)。
如果您的编译器已经支持lambda函数(也是下一个标准的一部分,但已经受到例如GCC和VC的最新版本的支持),您也可以使用其中一个:
setRxHandler( [](){obj.comm_rxHandler();} );
答案 2 :(得分:0)
就像现在一样,setRxHandler
原型获取一个指向函数的指针,该函数不返回任何内容并且需要int
。正如您所注意到的,这不适用于成员函数,因为它们不能像普通函数一样被调用(您还必须处理this
指针,这意味着要让该类的实例调用方法)。
要使它既可以使用成员函数又可以使用非特定的(泛型),您必须创建一个基类,并且要使用所有要使用的类setRxHandler
并使用派生自那个班:
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:
或使用模板:
template<typename T>
void setRxHandler(void (T::*h)(int)) { ... }
使用模板选项,您实际上无法控制将使用setRxHandler
(不包括RTTI)的类,这可能正是您想要的。
答案 3 :(得分:0)
您可以为Y
创建基类并使用它(以避免“特定于类”),或使用模板:
template <class T>
setRxHandler(void (T::*h)(int));
但是这可能会引发如何使用成员函数的问题(如果有的话,请告诉我们)。
答案 4 :(得分:0)
正如其他人已经提到的,C ++不提供此功能。
您可以使用的另一个选项是libsigc++,它在gtkmm中广泛使用,请参阅教程中的this example,例如如何将指针传递给成员函数。您的示例可能类似于:
// sigc::slot<void, int> is a 'slot' to hold a function with return type void
// and 1 int argument.
void setRxHandler(sigc::slot<void, int> slot);
void comm_rxHandler(int status);
//sigc::mem_fun() can convert a member function to a function slot.
x.setRxHandler(sigc::mem_fun(*this, &X::comm_rxHandler));