首页 > 解决方案 > lambda 函数和函数类型定义如何作为侦听器工作?

问题描述

我正在尝试从 Java 中制作相当于事件侦听器,但在 C++ 中。我的目标是,我可以从一个类中调用一个函数,这会触发我添加到这个类中的监听器。

我找到了以下链接,它为我提供了解决方案。

特此的问题是,我的程序在我尝试调用侦听器时立即崩溃。

我的代码结构如下:

class MessageHandler abstract
{ 
public:
    typedef const std::function<void(int, std::string)> Handler;
    void addHandler(Handler& handler) {
            handlers.push_back(&handler);
    }
private:
    std::vector<Handler*> handlers;
protected:        
    void someFunction(int id, std::string message) {
        for (auto& handler : handlers) {
            (*handler)(id, message); //Here it will crash
        }
    }
};

正如您可能已经提到的,这是我从中派生一些子类的基类。然后这些子类调用我的“someFunction”代码。

我创建这些子类之一的类的结构如下:

class Server
{
private:
    SubHandler handler;

    void setHandlers() {
        handler.addHandler([&](int id, std::string message) { executingFunction(id, message); });
    }

    void executingFunction(int id, std::string message) {
        std::cout << "Listener Worked!" << std::endl;
        //Not actually the code inside, but it doesn't matter, case I don't even get to this code
    }
};

该程序在该行崩溃,我在其中循环我的侦听器并错误地调用它们:

“在位置 0x000000000000000010 读取时访问冲突。”

(这是翻译的,所以如果您将 Visual Studio 设置为英语,这不是您将收到的消息)

标签: c++

解决方案


您应该使用/permissive-. 编译器应该拒绝你的代码。

void addHandler(Handler& handler) {
        handlers.push_back(&handler);
}

你不应该能够向这个函数发送一个临时的,但你是!

//                 v----- This lambda is a temporary object --------------------------v
handler.addHandler([&](int id, std::string message) { executingFunction(id, message); });

在该行创建的 lambda 对象在语句完成后立即死亡。

//                 v---- pointer to the temporary.
handlers.push_back(&handler);

我的建议是删除指针并按std::function值使用对象。它们被设计成这样使用:

//  abstract is not a C++ keyword.
class MessageHandler /* abstract */
{ 
public:
    // using instead of typedef and non const
    using Handler = std::function<void(int, std::string)>;

    void addHandler(Handler const& handler) { // const reference
            // insert by value
            handlers.push_back(handler);
    }
private:
    // no pointer here.
    std::vector<Handler> handlers;
protected:        
    void someFunction(int id, std::string message) {
        for (auto const& handler : handlers) {
            handler(id, message); //Here it will not crash anymore
        }
    }
};

推荐阅读