0

我正在使用 C++ 的 Arduino 机器上运行一些代码。设置(非常粗略)如下面的主要功能。这个例子相当做作,代码设计并没有真正通过气味检查,但这是我能做的最好的。

有一个第 3 方 WiFi 库,我正在尝试添加一个“onDisconnect”挂钩。当我的 TaskRunner 类执行时,我将一个函数附加到这个钩子上,以便当 WiFi 断开连接时,我的任务运行器会收到通知。

挑战是我不太了解该语言,无法分配一个匿名函数,该函数还保持“isWifiConnected”的范围。我正在学习 C++,所以请随意更改问题的标题,因为我可能不会甚至问对的人。

请注意,我可能不是在寻找匿名函数。我正在尝试在调用 onDisconnect() 时更新 isWifiConnected 属性。

#include <iostream>
using namespace std;


// A 3rd Party class
// https://github.com/Hieromon/AutoConnect/blob/master/src/AutoConnect.h
// https://github.com/Hieromon/AutoConnect/blob/master/src/AutoConnect.cpp
class AutoConnect {
     public:
        AutoConnect(){};

        // I add this to the class as a hook to be called at about
        // line 549 code block where AutoConnect calls disconnect code
        void (*onDisconnect)();
};



void onDisconnect(){
    cout << "Disconnecting!" << endl;
    cout << "But how to make isWifiConnected false?  I don't have access :/";
};


// My task runner 
class TaskRunner {

    public:
        bool isWifiConnected;
        AutoConnect *connector;

        TaskRunner(AutoConnect & connector){
           this->connector = & connector; 
        }

        void execute(){

            isWifiConnected = true;
            // run some WiFi connection code ...

            // assign the onDisconnect hook to be run when it disconnects
            connector -> onDisconnect = onDisconnect;

            // but how can I update "isWifiConnected" = false when the onDisconnect runs

            // In JavaScript, I could do
            /*
                connector -> onDisconnect = function(){
                    // variable stays in scope due to closure.
                    isWifiConnected = false;
                }
            */
        }
};




   int main() {
        cout<<"Running ..." << endl;

        // Instantiate my classes and inject WifiConnector into my task runner
        AutoConnect connector;
        TaskRunner runner = TaskRunner(connector);

        // Simulate an event loop for effect
        for(int i = 0; i < 10; i++){
            if(i == 0) runner.execute();
            // on some other condition, Wifi is disconnected
            if(i == 9)  connector.onDisconnect();
        }

        return 0;
    }

关于如何更新 TaskRunner 的 isWifiConnected 变量的任何想法?我尝试了各种指针组合,但不能完全正确。

4

1 回答 1

1

除了代码的其他问题(见问题评论):

您可以将 lambda 存储在 a 中std::function

而不是void (*onDisconnect)();声明它std::function<void()> onDisconnect;。(需要#include<functional>

然后你可以在其中存储一个捕获 lambda:

connector->onDisconnect = [this](){
    isWifiConnected = false;
};

由于这存储了一个指向 的指针*this,因此您必须确保该TaskRunner对象比对该钩子/ lambda 的任何潜在调用都更有效。否则你的程序会有未定义的行为

特别是目前在in 对象TaskRunner之后声明了,这意味着后者将在 之前被销毁,因此当已经被销毁时将有可能调用 lambda。如果的析构函数可以调用 lambda,则尤其如此。有没有我不知道。AutoConnectmainAutoConnectTaskRunnerAutoConnect

于 2020-02-08T00:29:43.027 回答