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??
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
};
Related
How to make simple button class to call custom function on press. Some code example:
class Button
{
public:
Button();
Draw();
Press();
SetCallback(void(*cback)());
priate:
void (*callback)();
}
void Button::SetCallback(void(*cback)())
{
callback = cback;
}
class GameState
{
...
}
class MenuState : public GameState
{
Button *btn;
}
class Game
{
...
}
bool Game::Init()
{
std::unique_ptr<GameState> menu = std::unique_ptr<MenuState>(new MenuState);
}
void Game::PopState(){
states.pop_back();
}
How to set callback in button to Game::PopState() function in this example. I need Then I press button it call Game::PopState function.
What you're looking for is a tutorial on function pointers, which can be found here.
If you need to pass an argument, your button function pointer should either have a pointer or a reference to your Game object, as member functions require references( to which object owns the function call). If the popstate function in your Game class is private you may need to make it public or a friend function.
You should be able to modify the example below by replacing the string reference with a reference to the Game object. If you need a more generic callback look into templates(better but a bit more complicated) or type punning(generally considered bad practice)
#include <iostream>
#include <string>
class Button
{
public:
void SetCallback(void(*cback)(std::string&));
void Press(std::string str){
//Make sure some sort of check is done in order to prevent undefined behavior from a call
if(callback != nullptr)
callback(str);
}
Button(){
callback = nullptr;
}
private:
void (*callback)(std::string&);
};
void Button::SetCallback(void(*cback)(std::string&))
{
callback = cback;
}
//Method 2 for calling function
void DoStuff(std::string& str){
std::cout << str;
}
int main(void){
Button btn;
//Method 1 for calling function, replace body with Game.PopStates();
auto foo = [](std::string& str){ std::cout<<str.size();};
btn.SetCallback(foo);
btn.Press("A");
//Method 2 for calling function
btn.SetCallback(&DoStuff);
btn.Press("\nPressed Button");
return 0;
}
Your function pointer for Game should be something like this:
void SetCallback(void(*cback)(Game&));
You can call it like this:
auto foo = [](Game& g){ g.DoStuffInClass(); };
btn.SetCallback(foo);
btn.Press(game);
The above examples work fine and are usually all you need to do, but this article here goes more in-depth about member function pointers. The main takeaway from the article is typedef is another way for writing member function pointers like shown:
typedef int (Fred::*FredMemFn)(char x, float y); // Please do this!
All the above does(when implemented with PopStates), however, is lock your button callback into using void functions called by your Game objects, which limits your ability to use the button. You can use a pointer instead of a reference if you want to allow special cases for acting without a Game object, but either way your Game object has to find some way of being put in inside your callback.
Preface
I am trying to create an event system. An event will do nothing by default. If an object needs to opt into the event system, then all that is required is that the programmer defines a callable function for the listener.
In theory, this sounds great, but in reality I am not sure if it is possible to implement this sort of thing within C++. Here is an example of what I imagine the code to look like.
Outline
#include <iostream>
enum Color{ red, green, blue };
class Event {
public:
// Would be called within the context of a loop.
// Each time we go through the loop, we would have different input.
void listen(const Color& color) {
// If the callable is defined, then call it.
if(callable) callable(color);
}
// We would pass in function to be called within listen()
void defineAction(void(*function)(const Color &color)) {
callable = function;
}
private:
void (*callable)(const Color& color) = nullptr;
};
class Greeter: public Event {
void greet() { std::cout << "Hello" << std::endl; }
};
int main(int argc, char** argv) {
Greeter greeter;
// This doesn't work for two reasons. We cannot define a function here,
// and scoping rules wont allow for an implicit this->greet().
// Ideally, I would like to do this inline with a lambda
/*void greetIfRed(const Color& color) {
if(color == red)
// call greet().
}
greeter.defineAction(&greetIfRed);
*/
}
Expanding on this idea
Basically, the Event class will receive something that will be changing each time we go through the event loop. I chose color for this example, but it could be mouse coordinates, an integer, or something else. That type will need to be strictly defined before hand.
In my design, I don't want it to matter what classes we have within the event loop. We could have a greeter, a player, or something that just says farewell. I imagine that the event loop would look something like this. (psuedocode)
while(event) {
greeter.listen(event)
player.listen(event)
text.listen(event) // e.g.,the text could change color if the mouse is over it,
}
The Question
Is it possible to define a method outside a class's scope via a function pointer that utilizes said class's methods? This would need to work for a sub class. The class Greet and the function greetIfRed capture the functionality that I am trying to achieve.
So, I experimented with many suggestions, and I managed to create a working example without many changes. I compiled this with C++14.
#include <iostream>
#include <functional>
enum Color{ red, green, blue };
class Event {
public:
void listen(const Color& color) {
if(callable) callable(color);
}
void defineAction( std::function<void(const Color& color)> function) {
callable = function;
}
protected:
std::function<void(const Color& color)> callable = nullptr;
};
class Greeter: public Event {
public:
void greet() { std::cout << "Hello" << std::endl; }
};
int main()
{
Greeter greeter;
greeter.defineAction([&greeter](const Color& color){
if(color == red)
greeter.greet();
});
greeter.listen(red);
greeter.listen(green);
}
I'm making a program were all the buttons need to be in a vector so I can easily call the render function for all of them with a for loop. I created a shortened down version of my problem. So the code below has the class called Button. When I create a Button variable I have to send the class containing the function I want to be called and the function pointer in the template. When I call the buttons Pressed function it will call the function I sent. When I call the buttons Render function it will render. I then have two different classes with functions that should be called when there corresponding button is pressed. I haven't used templates before so i'm not sure how I would put the buttons into a vector if the buttons have different template parameters so i cant write:
for (int i = 0; i < buttons.size(); i++) {
buttons[i].Render();
}
instead of:
button1.Render();
button2.Render();
button3.Render();
but...
Right so here is the code:
template<class CWF> //CWF = Class with Function
class Button {
public:
typedef void(CWF::*eventMethod)();
Button(CWF& cwf_, eventMethod method_) : method(method_), cwf(cwf_) {};
~Button() {}
void Pressed() {
(cwf.*(method))();
}
void Render() {};
private:
eventMethod method;
CWF& cwf;
};
Class1 class1;
Class2 class2;
Button<Class1> button1 = Button<Class1>(class1,&Class1::MyButtonWasPressed);
Button<Class2> button2 = Button<Class2>(class2, &Class2::MyButtonWasPressed);
int main() {
// loop here
button1.Render();
button2.Render();
//
//exiting herer
string line;
getline(cin, line);
return 0;
}
The best option in your example is to just remove the template altogether, and instead pass a std::function with your callback.
However, if your needs are complicated enough that that is not feasible, you would need to implement some form of type erasure. The most intuitive way would be to make your template class derive from some interface that provides the functions you need:
class AbstractButton {
public:
virtual void Pressed() = 0;
virtual void Render() const = 0;
};
template <typename CWF>
class Button : AbstractButton {
public:
// ...
void Pressed() override { /* ... */ }
void Render() const override { /* ... */ }
};
To use:
// store in vector
std::vector<std::unique_ptr<AbstractButton>> buttons;
buttons.push_back(std::unique_ptr<AbstractButton>(new Button<Class1>(/* ... */)));
// (or std::make_unique if you have C++14)
// use:
buttons[i]->Render();
So basically I'm making buttons in a game, and the buttons are a called Button.
The class i want the function from to store is called SoccerLevelsClass. I've tried looking into function pointers, but I'm not sure what's going on though i think it's the correct thing to do.
I want to save the function of SoccerLevelsClass as a member of Button.
Would i do something like this?
//MenuButton.h
#ifndef MenuButton
#define MenuButton
....
class Button
{
public:
Button(void(*SoccerLevelsClass::func)());
void (*SoccerLevelsClass::function)();
....
}
#endif
//MenuButton.cpp
#include <MenuButton.h>
Button::Button(void(*SoccerLevelsClass::func)())
{
function=func; //something like this
}
I know the code is probably way off, but I'd like to know if anybody has any suggestions.
All i really want to know is if it's possible.
Yes, this can be done - either with function pointers like in your example, or with lambdas if you can use C++11.
However, since you want to call a bound function of another class, you would need to pass/store pointer to an instance of that class as well to do that, unless the function is static.
In C++11, this is trivial:
std::function<void(void)> _f;
void apply() {
_f();
}
Bar(void (Foo::* f)()) {
_f = std::bind(f, Foo());
}
In C++03, this is a little tricky. Note in both versions I construct a temporary to call the member function, but I'm not sure whether it is necessary to store an instance of the class.
#include <iostream>
#include <functional>
struct Foo
{
Foo() { }
void stuff() {
std::cout << "hi\n";
}
};
struct Bar
{
void (Foo::* _f)();
void apply() {
(Foo().*_f)();
}
Bar(void (Foo::* f)()) {
_f = f;
}
};
int main()
{
Bar bar(&Foo::stuff);
bar.apply();
}
For what you are trying to do I would use the observer pattern:
class IFootballObserver
{
public:
virtual void OnBallKicked() = 0;
virtual ~IFootballObserver() {}
};
class Fooball
{
public:
Fooball(IFootballObserver& obs)
: mObs(obs)
{
// Call the observer interface at any time like so:
mObs.OnBallKicked();
}
private:
IFootballObserver& mObs;
};
class Button : public IFootballObserver
{
public:
// Football could be passed in/owned by something else
Button() : mFootball(*this) { }
void DoSomething()
{
// Called when foot ball is kicked
}
private:
virtual void OnBallKicked()
{
DoSomething();
}
Fooball mFootball;
};
I find this easier than using function pointers/std::function. Plus you could have a vector of observers and notify many objects of events.
I want to store a function as a class member and call it inside the class? Pretty much like a callback function. My class draw a document but every document must drawn differently. So I want to assign a function (written outside of the class) into one of the members of the class and then call it when I want to draw the document.
This function mostly is responsible for transforming objects according to each specific document.
Here is my class:
class CDocument
{
public:
CDocument();
~CDocument();
void *TransFunc();
}
void Transform()
{
}
int main()
CDocument* Doc = new CDocument();
Doc->TransFunc = Transform();
}
I know that this is probably simple question, but I couldn't find the answer by googling or searching SO.
I think, this is what you might want. Please get back to me if you have questions.
class CDocument
{
public:
CDocument():myTransFunc(NULL){}
~CDocument();
typedef void (*TransFunc)(); // Defines a function pointer type pointing to a void function which doesn't take any parameter.
TransFunc myTransFunc; // Actually defines a member variable of this type.
void drawSomething()
{
if(myTransFunc)
(*myTransFunc)(); // Uses the member variable to call a supplied function.
}
};
void Transform()
{
}
int main()
{
CDocument* Doc = new CDocument();
Doc->myTransFunc = Transform; // Assigns the member function pointer to an actual function.
}
You need to use a Pointer to member function.
typedef void (CDocument::*TransFuncPtr)();
And then you can use TransFuncPtr as an type.
With your edit It seems like you just need a Pointer to a Free function.
Here is a small working sample.
#include<iostream>
#include<string>
typedef void (*TransFuncPtr)();
class Myclass
{
public:
TransFuncPtr m_funcPtr;
};
void doSomething(){std::cout<<"Callback Called";}
int main()
{
Myclass obj;
obj.m_funcPtr = &doSomething;
obj.m_funcPtr();
return 0;
}
The C declaration syntax, inherited by C++, is tricky.
Your declaration
void *TransFunc();
is actually the same as
void* TransFunc();
which declares a function returning a pointer, and not a pointer to a function.
To have the * bind to the declared name, and not to the type, you have to use an extra set of parenthesis
void (*TransFunc)();