绑定类方法并将其作为函数指针传递

时间:2017-10-11 16:10:43

标签: c++ function c++11 bind

我想将我的类方法作为参数传递给(第三方)函数  ( listner - 无法更改)接受函数指针和void*。以下是一个例子:

#include <functional>

typedef void(*pfnc) (void*);

struct Foo
{
    static void static_foo(void*)
    {
    }

    void foo(void*)
    {
    }

    void listner(pfnc f, void* p)
    {
       f(p);
    }

    void test()
    {
        listner(static_foo); // works with static method

        auto f = [](void*) {};
        listner(f); // works with lambda

        std::function<void(void*)> stdf = std::bind(&Foo::foo, this, std::placeholders::_1);
        listner(stdf);  // does not compile with not static method
    }
};

不幸的是我的解决方案无法编译。我需要改变什么?

3 个答案:

答案 0 :(得分:1)

从回调信号的外观来看,侦听器API将指向void的指针作为“用户定义的数据”。您可以将this作为数据传递,并将一个小的无状态代理函数传递给Foo上的处理程序:

typedef void(*pfnc) (void*);

struct Foo
{
    static void static_foo(void*)
    {
    }

    void foo()
    {
    }

    void listner(pfnc f, void* user_data)
    {

        // eventually calls
        f(user_data);
    }

    void test()
    {
        listner(static_foo, nullptr); // works with static method

        auto f = [](void*) {
        };
        listner(f, nullptr); // works with lambda

        listner([](void* pv)
        {
            reinterpret_cast<Foo*>(pv)->foo();
        }, this);
    }

};

答案 1 :(得分:0)

对于问题中的示例,可以传递成员函数指针。但是当然必须知道要调用该成员的实例。如果调用函数也是成员函数,那么我们可以使用this来调用通过指针传递的成员函数。

struct Foo
{
    static void static_foo(void*)
    {
    }

    void foo(void*)
    {
    }

    void listner(pfnc f)
    {
    }

    void listner(void(Foo::*f)(void*))
    {
        (this->*f)(nullptr); // call member function pointer for this
    }

    void test()
    {
        listner(static_foo); // works with static method

        auto f = [](void*) {};
        listner(f); // works with lambda

        listner(&Foo::foo); // pass pointer to member function
    }
};

答案 2 :(得分:0)

您的示例“适用于”静态成员函数,因为它们几乎等同于普通旧函数

它也适用于您提供的lambda,因为它是一个无捕获 lambda,可以转换为函数指针(cf Passing lambda as function pointer) 然而,它不适用于具有捕获的lambda,因为,如chris所述,函数指针没有状态,即没有地方存储将被捕获的内容。

绑定也是如此。您可以将它存储在std :: function中,因为这样的对象具有状态,但是您不能将它存储在普通(无状态)函数指针中。

如果您不相信,请查看stdf.target_type()告诉您的内容并将其与typeid(static_foo).name()进行比较 您还可以查看std :: bind

的返回类型

最后,正如其他人所说,你必须将你的对象放在用户数据中,即在void *中。 可能值得研究一下你是否可以将std :: function作为参数包装在一个辅助函数中...