首页 > 解决方案 > 通过引用传递对象函数

问题描述

我试图通过引用传递一个对象函数。我只能用一个简单的功能让它工作。

代码:

class Light {

  ...... omitted some code here, not relevant .......

  void toggle2() {
    Serial.println("TOGGLE");
  };
}
class Button {
  public:
    OneButton pin;
    void single();

    Button(int _pin, void (&_single)() ){
      pin = OneButton(_pin, false, false);

      _single();
      pin.attachClick(_single);
    }
};
Light lights[] = {
  Light("Cozinha", CONTROLLINO_A15, CONTROLLINO_R0)
};
Button buttons[] = {
  Button(CONTROLLINO_A0, lights[0].toggle2)
};

上面的代码给出了按钮声明错误

no instance of constructor "Button::Button" matches the argument list -- argument types are: (int, void ())

toggle2function 是一个 void 函数,但程序可能因为 Light 类型而令人困惑?

如果我用一个简单的函数编写代码,它会很好地工作,如下所示:

void toggle() {
  Serial.println("TOGGLE");
};

Button buttons[] = {
  Button(CONTROLLINO_A0, toggle)
};

有什么建议吗??

标签: c++arduino

解决方案


我已经消除了代码示例中的所有干扰,专注于传递和调用函数指针的方法。

class Light {
public:
  void toggle2() {
  };
};
class Button {
  public:
    Button(int _pin, 
           void (Light::*single)(),  // the function. Compiler needs to know the class 
                                     // the function belongs to or it'll assume a free 
                                     // function
           Light& light) // class instance to invoke the member function on
    {
        (light.*single)(); // note the weird-looking invocation syntax.
                           // all of it is essential and easily <expletive deleted>ed up.
                           // C++FAQ recommends using a macro to keep from leaving 
                           // anything out. They don't recommend macros lightly.
                           // note you will want to store these two variables as Button 
                           // class members rather than using them immediately.
                           // I did the call in the constructor to keep the example simple.
    }
};

Light lights[] = {
  Light()
};

Button buttons[] = {
  Button(1, // the pin
         &Light::toggle2, // address of the fully-qualified member function 
         lights[0]) // instance to invoke member function on
};

可以在指向成员函数的指针中找到血淋淋的细节和一些非常好的建议

请注意,由于Button现在必须携带Light对其使用的实例的引用,因此在范围足够广的函数中创建lightsButtons局部变量变量是一个有吸引力的选择。

std::function为了完整起见,下面是Lambda 表达式的样子。

#include <functional>

class Light {
public:
  void toggle2() {
  };
};
class Button {
  public:
    Button(int _pin, 
           std::function<void()> single){ // std::function contains the necessary 
                                          // instance reference
        single(); // no muss, no fuss function call
    }
};
Light lights[] = {
  Light()
};
Button buttons[] = {
  Button(1, 
         [](){lights[0].toggle2();}) // lambda expression wrapping the function call
};

推荐阅读