使用 C++ lambda 指向成员函数的指针

Pointer to member function using C++ lambda

我正在尝试找到一种方法来提供指向不同 class 实例之间的成员函数的指针。目前,我能够提供指向不带参数的成员函数的指针,但当要指向的函数有参数时无法做到这一点。

一个示例代码来说明我的问题:

#include <iostream>

class Event
{
public:
    std::string type;
    Event(std::string type):type(type){}
};

class EventDispatcherBase
{
public:

    void addEventListener(std::function<void(Event &event)> listener)
    {
        Event myEvent("Type of the myEvent object");
        listener(myEvent);
    }
};

class EventDispatcherClass:public EventDispatcherBase
{
public:
    EventDispatcherClass()
    {
        addEventListener([](Event &event){std::cout << event.type << std::endl;});
        //addEventListener([this]{listener(Event event);});
    };

    void listener(Event &event)
    {
        std::cout << event.type << std::endl;
    }
};

int main()
{
    EventDispatcherClass eventDispatcherClass;

    return 0;
}

此代码使用匿名 lambda 表达式并在控制台中输出 "Type of the myEvent object"。但是如果我取消注释行

addEventListener([this]{listener(Event event);});

在EventDispatcherClass的构造函数中为了传递指向void listener(Event &event)成员函数的指针,编译器抛出如下错误:

no viable conversion from '(lambda at .../main.cpp:27:26)' to 'std::function'

我不明白为什么。

but cannot manage to do so when the function to point to has an argument.

lambda 应该接受类型为 Event& 的参数,该参数将被转发到 lambda 内部的成员函数。所以改成

addEventListener([this](Event &event){listener(event);});
//                     ^^^^^^^^^^^^^^

LIVE

工作线:

addEventListener([](Event &event){std::cout << event.type << std::endl;});

看起来一点也不像坏掉的:

//addEventListener([this]{listener(Event event);});

所以从一点一点地改变 working 行开始。

  1. 添加您想要的捕获表达式,它仍然有效

    addEventListener([this](Event &event){std::cout << event.type << std::endl;});
    
  2. 把body改成你想要的,还是可以的

    addEventListener([this](Event &event){ this->listener(event); });
    

如果您无法看出这两个版本之间的不同之处 - 这实际上在您自己编写它们时很常见并且您看到的是您打算键入的内容那里有什么 - 尝试更改布局以将所有内容排列起来(这样您会看到丢失的 (Event &event)),或者如上所述将一个转换为另一个 step-by-step,或者只是将一个替换为另一个并进行比较文件版本。

只需将其更改为addEventListener(listener);

并将函数本身设为静态 static void listener(Event &event)