Reputation: 89
I'm trying to pass an object function by reference. I can only make it work with a simple function.
Code:
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)
};
the code above gives an error on button declaration
no instance of constructor "Button::Button" matches the argument list -- argument types are: (int, void ())
toggle2
function is a void function but maybe the program is confusing because of the Light type?
If I make the code with a simple function it works well, like this:
void toggle() {
Serial.println("TOGGLE");
};
Button buttons[] = {
Button(CONTROLLINO_A0, toggle)
};
Any suggestion??
Upvotes: 1
Views: 118
Reputation: 33932
I've removed all of the noise from the code sample to focus on the how-tos of passing and calling a function pointer.
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
};
The gory details, and some very good suggestions, can be found at Pointers to Member Functions
Note that since Button
must now carry around the a reference to the Light
instance it uses, making lights
and Buttons
local variable variables in a sufficiently widely scoped function is an attractive option.
For completeness, here's what it looks like with std::function
and a Lambda Expression.
#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
};
Upvotes: 1