29

std::function我可以通过使用带有捕获子句的 lambda 表达式包装成员函数来轻松地将它们绑定到 a 。

class Class
{
    Class()
    {
        Register([=](int n){ Function(n); });
    }

    void Register(std::function<void(int)> Callback)
    {

    }

    void Function(int Number)
    {

    }
};

但我想直接绑定它们,如下所示。

// ...
Register(&Class::Function);
// ...

我认为根据 C++11 标准,应该支持这个。但是,在 Visual Studio 11 中,我得到了这些编译器错误。

错误 C2440:“换行符”:无法从“int”转换为“类 *”

错误 C2647:“.*”:无法取消引用“int”上的“void (__thiscall Class::*)(int)”

4

5 回答 5

51

我认为根据C++11标准,这个应该是支持的

不是真的,因为非静态成员函数有一个类型为 (cv-qualified) 的隐式第一个参数YourType*,所以在这种情况下它不匹配void(int)。因此需要std::bind

Register(std::bind(&Class::Function, PointerToSomeInstanceOfClass, _1));

例如

Class c;
using namespace std::placeholders; // for _1, _2 etc.
c.Register(std::bind(&Class::Function, &c, _1));

编辑您提到这将使用相同的Class实例调用。在这种情况下,您可以使用一个简单的非成员函数:

void foo(int n)
{
  theClassInstance.Function(n);
}

然后

Class c;
c.Register(foo);
于 2013-06-16T09:20:33.920 回答
42

根据 Stephan T. Lavavej -“避免使用 bind(),...,使用 lambdas”。 https://www.youtube.com/watch?v=zt7ThwVfap0&t=32m20s

在这种情况下:

Class()
{
    Register([this](int n){ Function(n); });
}
于 2016-04-13T10:58:23.157 回答
9

您可以使用std::bind

using namespace std::placeholders;  // For _1 in the bind call

// ...

Register(std::bind(&Class::Function, this, _1));
于 2013-06-16T09:20:58.780 回答
5

在 C++ 17 中,您可以使用:

Register([=](auto && ...args){ return Function(args...); });

这很甜蜜,尤其是在参数列表较长的情况下。当然,成员函数的参数列表必须与std::function' 的参数列表兼容。

于 2019-07-19T13:54:53.947 回答
2

使用std::functionand std::bind,您可以将不同的类成员函数视为相同。

#include <iostream>
#include <functional>
#include <vector>
using namespace std;
using namespace std::placeholders;

class Foo
{
public:
    void foo(const string &msg)
    {
        cout << msg << '\n';
    }
};

class Bar
{
public:
    void bar(const string &msg, const string &suffix)
    {
        cout << msg << suffix << '\n';
    }
};

int main(int argc, char **argv)
{
    Foo foo;
    Bar bar;

    vector<function<void (const string &msg)>> collection;
    collection.push_back(bind(&Foo::foo, &foo, _1));
    collection.push_back(bind(&Bar::bar, &bar, _1, "bar"));

    for (auto f : collection) {
        f("foo");
    }

    return 0;
}
于 2013-08-13T11:29:53.660 回答