C ++:对象将Lambda存储到结构中,并在以后调用该函数

问题描述 投票:0回答:2

完成此操作的正确语法是什么?想法是任何类的某个对象都可以在类GuiButton中存储一个lambda表达式,然后在以后访问该lambda表达式并访问其自己的局部变量。

应注意,我的平台(Arduino)不支持functional标头。

我为试图表达这个想法而编写的代码(由于lambda表达式无法访问ExampleScreen的成员,因此无法编译:

struct GuiButton {
    uint8_t x;  //coordinates for displaying this GUI element
    uint8_t y;
    GuiButton(uint8_t _x, uint8_t _y, void (*_callback)()) :
      x(_x),
      y(_y),
      callback(_callback)
      {};
    virtual void draw(bool _highlight);
  public:
    void (*callback)();   //to be executed BY THE PARENT OBJECT when this element is clicked
};

struct GuiTextButton: public GuiButton {
  char* text;   //text to display in this GUI element
  GuiTextButton(uint8_t _x, uint8_t _y, char* _text, void (*_callback)()) :
    GuiButton(_x, _y, _callback),
    text(_text)
    {};
  void draw(bool _highlight);
};

class ExampleScreen{
  private:
    GuiButton** buttonPtr;
    uint8_t buttonCount;
    uint8_t selectedButton;
    bool proc1Active;
    bool proc2Active;
  public:
    ExampleScreen() : 
      buttonPtr(NULL),
      buttonCount(0),
      selectedButton(0),
      proc1Active(false),
      proc2Active(false)
        {
          //different derived classes of GuiScreen shall have different constructors to define
          //their visual and functional elements
          buttonPtr = new GuiButton* [2];
          buttonCount = 2;
          {
            char text[] = "Button1";
            GuiButton *_thisPtr = new GuiTextButton(5,0,text, []() {
              proc1Active = ~proc1Active;
            });
            buttonPtr[0] = _thisPtr;
          }
          {
            char text[] = "Button2";
            GuiButton *_thisPtr = new GuiTextButton(5,0,text, []() {
              proc2Active = ~proc2Active;
            });
            buttonPtr[2] = _thisPtr;
          }
        };
    void click() {
      void (*callback)() = (buttonPtr[selectedButton]->callback);
      callback();
    };
};

int main() {
  ExampleScreen gui;
  gui.click();
};
c++ class pointers lambdaexpression
2个回答
1
投票

遵循这些原则:

class GuiButton {
  GuiButton(void (*_callback)(void*), void* _context)
      : callback(_callback), context(_context) {}

  // Invoke the callback as callback(context)
  void (*callback)(void*);
  void* context;
};

// In ExampleScreen
new GuiButton([](void* context) {
    auto self = static_cast<ExampleScreen*>(context);
    self->proc1Active = ~self->proc1Active;
}, this);

0
投票

根据您在讨论中的评论,您不能使用functional标头来排除简单的解决方案(即,使回调为std::function并捕获上下文或使用std::bind绑定它。

但是,我认为您仍然可以做您想做的事。将callback的类型设置为struct,例如:

struct CallbackData {
  void (*callback)(ExampleScreen*);
  ExampleScreen* context;
  // obvious constructor here...
}

然后您可以像这样调用回调:

callback_data.callback(callback_data.context);

然后将其传递给GuiButton构造函数,如:

new GuiTextButton(5,0,text,CallbackData([](ExampleScreen* e) { ... }, this));

也许更好的选择是使用functor。为此,您将创建一个类似的类:

class GuiButtonCallback {
 public:
  GuiButtonCallback(ExampleScreen* context) : context_(context) {}
  void operator() {
    context->proc1Active = ~context->proc1Active;
  }
 private:
  ExampleScreen* context_;
};

然后您可以构造如下内容:

new GuiTextButton(5 , 0, text, GuiButtonCallback(this));
© www.soinside.com 2019 - 2024. All rights reserved.