我的C / C ++技能有点生锈,在过去的几年中,我主要从事Java工作。现在,我才开始玩Arduino,并做了一个简单的按钮类。我想添加一个事件监听器,所以我做了这样的事情:
class MyButton{
public:
MyButton(byte pin);
bool isPressed();
bool wasToggled();
bool wasPressed();
void eventLoop();
inline void setListener(MyButtonListener* listener) { _listener = listener; }
private:
byte _pin;
boolean _lastToggledState = false;
MyButtonListener* _listener;
};
class MyButtonListener{
public:
virtual void onPressed() = 0;
private:
};
eventLoop()
方法(旨在从Arduino loop()
函数调用),在侦听器类中调用onPressed()
方法:
void MyButton::eventLoop(){
if( wasPressed() && _listener ){
_listener->onPressed();
}
}
到目前为止,一切还好。但是我不知道如何在Arduino主文件中实际分配和使用监听器。来自Java,我习惯做类似的事情
myBtn.setListener( new MyButtonListener(){
void onPressed(){
Serial.println("Pressed");
toggleLed(); // toggleLed() is a method in the main Arduino file
}
});
通过声明一个使用toggleLed()
方法作为参数的新类,使它以非常复杂的方式工作(因为否则无法从新类内部访问它):
class BtnListener : public MyButtonListener{
public:
BtnListener(void* toggleFunction) : _toggleFunction(toggleFunction){ };
private:
void (*_toggleFunction)();
void onPressed(){
Serial.println("Pressed");
_toggleFunction();
};
};
myBtn.setListener( new BtnListener(toggleLed) );
在C ++中肯定有一种更便捷的方法来执行类似的操作吗?一个监听器是可行的(但是很丑)-我什至无法想象拥有10个按钮都需要不同监听器实现的恐怖...
答案 0 :(得分:2)
在您的情况下,一种或最简单的方法是将侦听器存储为std::function<void()>
,并且根本没有用于建模buttonlistener的实际类(如果您确实想封装它,但这不是必需的)。然后将lambda函数用于setListener调用,如下所示:
myBtn.setListener( [this]{
Serial.println("Pressed");
toggleLed(); // toggleLed() is a method in the main Arduino file
});
答案 1 :(得分:2)
由于默认情况下Arduino IDE似乎未包含<functional.h>
,因此我无法使用std::function<void()>
使用答案。但是,经过一些试验,我意识到有一种更简单的方法,它还具有能够对侦听器进行建模的好处。
listener类仅包含指向每个侦听器回调函数的函数指针,以及一个为每个回调采用参数的构造函数。然后,只需创建一个新的侦听器类实例并将每个回调作为lambda传递,将非常方便。
class MyButton{
public:
inline void setListener(MyButtonListener* listener) { _listener = listener; }
private:
MyButtonListener* _listener;
}
class MyButtonListener{
public:
MyButtonListener(void* onPressed, void* onToggled) : onPressed(onPressed), onToggled(onToggled) {};
void (*onPressed)();
void (*onToggled)();
};
void MyButton::eventLoop(){
if( _listener ){
if( wasPressed() ){
_listener->onPressed();
}
if( wasToggled() ){
_listener->onToggled();
}
}
}
myBtn.setListener(
new MyButtonListener(
// onPressed
[](){
Serial.println("Pressed");
toggleLed();
},
// onToggled
[](){
Serial.println("Toggled");
}
)
);
不确定此解决方案是否有任何缺点,但是它可以工作,可读且适合在Arduino上使用。