C++:保存特定实例中的方法的函数指针



所以我目前正在为C++游戏开发输入管理器。我正在考虑将其作为map<char, list<Listener::method>>来做,这样当我注册按下的按钮时,我会调用为特定键注册的所有方法。

问题是,这样做我必须指定要从中调用该方法的实例。有没有办法在变量中不仅保存方法,而且保存调用方实例?

像这样:

class Foo 
{
public:
    Foo ();
    ~Foo ();
    void DoSomething();
};

Foo fooObject;
void(Foo::*fPtr)(void) = &fooObject::DoSomething;
(*fPtr)();

这就叫fooObject DoSomething()

可能吗?

如果没有,有人可以指出我的事件侦听器模式吗?不必过于复杂或线程安全。只是基本结构。

成员函数指针的问题在于你需要一个类的实例来调用它们。 仅使用指针无法实现此目的,因为指针仅指向函数,而不是需要传递给函数的其他对象(请记住,所有成员函数都有一个采用类类型的隐式第一个参数)。

可以使用std::function来拥有一个函数对象,该对象保存要调用的对象和要调用的函数。 如果你有

std::function<void()> func = [&](){ return fooObject.DoSomething(); }; // Bind with a reference.  Use this if the object will live as long as the function to save on a copy
std::function<void()> func = [=](){ return fooObject.DoSomething(); }; // Bind with a copy. Use this if the function will outlive the object

然后,当您使用 func() 调用 func 时,它将运行 Lambda 的主体,该 lambda 在 fooObject 上调用DoSomething


您还可以使用 std::bind 将成员函数指针绑定到对象以调用它,但 lambda 通常是首选,因为语法易于使用。

有没有办法在变量中不仅保存方法,而且保存调用方实例?

是的,您可以将方法和对象绑定在一起。

C++11 以来,您拥有bind实用程序。


您的概念中的最小示例:

struct Foo {
  void foo();
};
void bar() {
  // your map
  std::map<char, std::function<void()>> actions;
  // Bind method and object together inside fn
  Foo foo;
  auto fn = std::bind(&Foo::foo, &foo);
  // Insert fn into map
  actions.emplace('f', fn);
  // call fn from map! Be careful about object lifetime
  actions['f']();
}

戈博尔特代码


请注意,因为"绑定对象"(在我的示例中fn)将只存储对对象的引用foo。因此,如果在对象foo被销毁后调用fn,您将获得未定义的行为


如果您想关心对象生存期,可以使用 lambda 函数复制它。例如:

auto fn = [foo]() { foo.foo(); }

或者使用自定义结构并将复制的对象存储在其中。

没有"来自特定实例的方法"这样的东西。

  1. 可以按住指向类的成员函数的指针。此类指针不绑定到任何特定对象。
  2. 可以在类的任何对象上使用该函数指针。

鉴于

class Foo 
{ 
  public:
    Foo ();
    ~Foo ();
    void DoSomething();
};

任何类都可以保存指向 DoSomething 成员函数的指针(您将其称为方法)。

void(Foo::*fPtr)(void) = &Foo::DoSomething;

您需要一个对象才能调用成员函数。调用语法有点迟钝,但就在这里。

Foo foo = <some function call>;
(foo.*fPtr)();

您可以使用 bind -function 来获取函数对象,该函数参数已绑定到参数。这样,您可以将对象引用(隐式是任何非静态成员函数中的第一个参数)绑定到您希望为其进行回调的相应对象:

class Foo
{
public:
    int x;
    Foo (int _x) : x(_x) {} ;
    void doSomething() { cout << x << endl; }
};

int main() {
    Foo fooObject1(1);
    Foo fooObject2(2);
    std::function<void ()> fx1 = std::bind(&Foo::doSomething,&fooObject1);
    std::function<void ()> fx2 = std::bind(&Foo::doSomething,&fooObject2);
    std::vector<std::function<void ()>> callbacks;
    callbacks.push_back(fx1);
    callbacks.push_back(fx2);
    for (auto f : callbacks) {
        f();
    }
}

输出:

1
2

相关内容

  • 没有找到相关文章

最新更新