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

发布于 2024-11-27 06:27:50 字数 653 浏览 1 评论 0原文

我有一个类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 技术交流群。

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

发布评论

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

评论(5

南冥有猫 2024-12-04 06:27:50

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

所以 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 以获取支持的现有实现这个用例以及更多。

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:

void setRxHandler(Y*, void (Y::*h)(int));

To invoke setRxHandler(), you need to pass it arguments as follows:

Y y;
setRxHandler(&y, &Y::comm_rxHandler);

In the setRxHandler() method, you can invoke the function pointer using this syntax:

void setRxHandler ( Y* y, void (Y::*h)(int) )
{
    // ...
    (y->*h)(0);
    // ...
}

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.

孤独难免 2024-12-04 06:27:50

将您的回调更改为:

void setRxHandler(std::function(<void(int)>);

然后您可以使用绑定器:(

setRxHandler( std::bind(&class_name::comm_rxHandler, obj) );

std::functionstd::bind 是即将推出的下一版本 C++ 标准的一部分。可能您的编译器已经附带了它们。如果没有,它们可能位于命名空间 std::tr1 中,如果其他方法都失败,您将在 boost - 这就是它们被发明的地方 - 作为 boost::functionboost::bind。)

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

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

setRxHandler( [](){obj.comm_rxHandler();} );

Change your callback to this:

void setRxHandler(std::function(<void(int)>);

Then you can use binders:

setRxHandler( std::bind(&class_name::comm_rxHandler, obj) );

(std::function and std::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 namespace std::tr1. If all else fails, you will find them at boost - which is where they were invented - as boost::function and boost::bind.)

You can, however, also pass non-member or static functions to setRxHandler, as well as function objects (which is the result of std::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( [](){obj.comm_rxHandler();} );
绻影浮沉 2024-12-04 06:27:50

现在,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),这可能正是您想要的。

As it is now, the setRxHandler prototype takes a pointer to a function that doesn't return anything and takes an int. 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 the this 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:

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:

or use templates:

template<typename T>
void setRxHandler(void (T::*h)(int)) { ... }

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.

成熟稳重的好男人 2024-12-04 06:27:50

您可以为 Y 创建一个基类并使用它(以避免“特定于类”),或者使用模板:

template <class T>
setRxHandler(void (T::*h)(int));

但这可能会引发如何使用成员函数的问题(您告诉我们如果是的话)。

You can either make a base class for Y and use that (to avoid being "class specific"), or use templates:

template <class T>
setRxHandler(void (T::*h)(int));

But then this may raise questions of how to use the member function (you tell us if it does).

梦行七里 2024-12-04 06:27:50

正如其他人已经提到的,C++ 不提供此功能。

您可以使用的另一个选项是 libsigc++ ,它在 gtkmm 中广泛使用,请参阅 这个示例在他们的教程中,例如如何将指针传递给成员函数。您的示例可能类似于:

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

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:

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