Pass in and store function pointer to object - c++

I'm writing a basic GUI framework as a school project and I'm trying to create an object (think a button) that, when interacted with, will call a particular function.
To explain my setup simply, I have a button class and a window manager class. The window manager is instantiated once from main and many buttons are instantiated from the window manager, with all 3 being in separate files. Nothing should go in main.
I'm a bit of a C++ noob, but as far as I can see, it would be best to use function pointers for this. My idea is to instantiate my button object then to pass it a function pointer to a function that when called would edit another object.
Firstly, I presume that the best way to do this would be to have the functions be defined locally to the window manager otherwise I'd have trouble with access? I had wanted to initially not have them listed in the header to make things easier (with a view to creating a kind of drag and drop editor in the future).
Second, how would I pass (from the window manager) a pointer to a function (which would exist within the window manager) to an instance of a button object? I thought I'd be able to treat it similarly to any other variable and do something as:
Button btn1 = new Button();
btn1->SetText("Button 1");
btn1->SetOnClick(functionpointer);
But, after looking through various tutorials I don't quite understand how I'd implement this. For example, how do I even define somewhere to store the function pointer in my button class?
Would appreciate any insight, I think I've confused myself enough for one day.
EDIT: Seems I should add that my Button and WindowManager classes are in separate files and my entry point so to speak is an instance of WindowManager. All the setup of my GUI including assigning a function to a button would be done in the constructor of WindowManager.

Here is one approach by using function pointers. However using std::function makes the code more flexible. For example you can use lambda expressions.
To use std::function you can simply change the typedef to typedef std::function<void(Button*)> EventCallback; and add the include #include <functional>
#include <iostream>
class Button
{
public:
// Typedef of the event function signature
typedef void(*EventCallback)(Button* button);
Button() : onClick(nullptr) {}
// Set the function to call
void SetOnClick(EventCallback func) { onClick = func; }
// Call the function if exists
void OnClick() {
if (onClick)
onClick(this);
}
private:
// This stores the function pointer for the button
EventCallback onClick;
};
// just some example function that has the same signature as Button::EventCallback
void MyEventFunc(Button* button)
{
std::cout << "Triggered" << std::endl;
}
int main() {
Button button;
button.SetOnClick(&MyEventFunc);
button.OnClick();
return 0;
}
http://ideone.com/x5O49B

You can do it with pointer to member function like this (in this case Button has to know WindowManager);
class WindowManager
{
public:
typedef void (WindowManager::* TypeOnClickFunc)( void );
void anyfunction( void ) {}
};
class Button
{
public:
Button( WindowManager * wm ) :_windowmanager( wm ) {}
void SetOnClick( WindowManager::TypeOnClickFunc fptr )
{
_onclickfptr = fptr;
}
void OnClick( void )
{
(_windowmanager->*_onclickfptr )( ); // indirect call WindowManager::anyfunction
}
private:
WindowManager *_windowmanager;
WindowManager::TypeOnClickFunc _onclickfptr;
};
WindowManager wm;
Button *btn1 = new Button( &wm );
btn1->SetOnClick( &WindowManager::anyfunction );
... or with pointer to static function like this ...
class WindowManager
{
public:
typedef void (*TypeOnClickFunc)( void );
static void anyfunction( void ) {}
};
class Button
{
public:
Button() {}
void SetOnClick( WindowManager::TypeOnClickFunc fptr )
{
_onclickfptr = fptr;
}
void OnClick( void )
{
(*_onclickfptr )( ); // indirect call static WindowManager::anyfunction
}
private:
WindowManager::TypeOnClickFunc _onclickfptr;
};
Button *btn1 = new Button();
btn1->SetOnClick( &WindowManager::anyfunction );
... with typdef in Button instead of WindowManager ...
class WindowManager
{
public:
static void anyfunction( void ) {}
};
class Button
{
public:
typedef void (*TypeOnClickFunc)( void );
Button() {}
void SetOnClick( TypeOnClickFunc fptr )
{
_onclickfptr = fptr;
}
void OnClick( void )
{
(*_onclickfptr )( ); // indirect call
}
private:
TypeOnClickFunc _onclickfptr;
};
Button *btn1 = new Button();
btn1->SetOnClick( &WindowManager::anyfunction );

Related

How to make work simple button class with callback?

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.

where to declare object to use it (fltk)

I am having a problem accessing an object or its methods in fltk.
I have a Class named MyWindow which is a child class of Fl_Window.
so basically i would like to use an object which is either declared int the main or Mywindow in private section. My problem is that I can't use it that way. It only lets me to use the object if it is declared global. Can i somehow put it on the heap like this: Classname *pointer = new Classname(); ? IF i can where do I do that?
How would the callback function work if i need that object or its functions in the callback?
Should i use a pointer to it in the callback arguements?
lets say i want to click on the button and I need it to do something with the object and change a value.
lots of questions I know, I am really lost.
Can someone just point me to the right direction? Thank you! :)
Simple case for passing data to the GUI
class MyData
{
// The data model
};
class MyWindow: public FL_Window
{
MyData* m_data;
public:
void Data(MyData* data) { m_data = data; }
...
};
int main()
{
MyWindow gui;
MyData data;
// Tell the gui about the data
gui.Data(data);
...
// Setup the dialog
gui.begin();
...
gui.end();
gui.show();
return FL::run();
}
For the callbacks, do it in two stages
class NeedingACallback
{
public:
void Setup()
{
...
FL_xxx* w = new FL_xxx(xpos, ypos, wid, hgt, name);
...
// v Pass the instance to the static
w->callback(_EventCB, this);
}
// The callback
static void _EventCB(FL_Widget* w, void* client)
{
// Convert the void* back to the instance
NeedingACallback* self = reinterpret_cast<NeedingACallback*>(client);
self->EventCB();
}
// Make life simple so you don't have to put self-> in front of
// all the instance data accessed
void EventCB()
{
// Callback for this instance of the class
}
};
EDIT It sounds like you're having multiple instances of data. An alternative technique is to have data as a reference. This must be done in the constructor. This way, m_data and the data in main both refer to the same area of memory.
class MyWindow: public FL_Window
{
MyData& m_data;
public:
MyWindow(int wid, int hgt, MyData& data, const char* title=0)
: FL_Window(wid,hgt,title)
, m_data(data)
{
...
}
};
int main()
{
MyData data;
MyWindow gui(100, 100, data, "Call me Mr");
...
// Setup the dialog
gui.begin();
...
gui.end();
gui.show();
return FL::run();
}

C++ an object with its own method?

I'm sorry, this is probably a stupid question. I am obviously misunderstanding something fundamental about object oriented programming. I am used to C and am now trying to use C++.
I have some buttons in a class called Button. Each button does something different. What I want to write is something like this:
Button button1;
Button button2;
...
void button1::onClick () {
...
}
void button2::onClick () {
...
}
But that does not work ("button 1 is not a class, namespace or enumeration" - yes I know!). I know I could just make a separate class for each button:
class button1_class : public Button {
public:
void onclick () {
...
}
} button1;
class button2_class : public Button {
...
}
But to me it 'feels' wrong to make a class when I know for sure it will only have one member.
I'm using Agui, a GUI library for Allegro 5.
EDIT
Thanks for the responses. While they are all helpful and (I think) all valid answers, nobody has actually said yet "no you cannot have an object with its own unique method because..."
So for example, if object1 is of type ObjectClass then object1 is not allowed to have a method (a member function) that is unique to object1, but rather possesses only the methods that are defined as part of ObjectClass. Is that right?
I'm sorry I did not include my actual use case. I was kind of more interested in just getting my head around OOP so that I can do it properly on my own.
EDIT2
Looking at the responses in more detail I suppose it is possible with lambda expressions, it's just not in the way I imagined it. Thanks again
The natural C++ way is to do as vsoftco explained, with virtuals and inheritance.
However, if your Button class has already everything needed, and the only thing that changes between the buttons is the unique (trhow-away) action to be performed, you may want to consider this alternative:
class Button {
function<void()> f;
public:
Button(function<void()> mf) : f(mf) {}
void onClick() { f(); }
};
This variant of your class uses a function object (think of it as a kind of function pointer but much more flexible to use).
You can then use it with lambda-functions as in this example:
int main(int ac, char**av)
{
Button button1([&]() { cout << "Hello 1!\n"; });
Button button2 ([]() { cout << "Hello 2!\n"; });
button1.onClick();
button2.onClick();
}
If the buttons have different functionalities, best thing to do is to create a BaseButton class in which you mark the onclick() as virtual (or make it pure virtual, which will make BaseButton an abstract class), then derive each other button from BaseButton, making sure to override onclick() in each derived class. You then need to use the buttons via a reference or pointer to a BaseButton, this way you achieve what is called "polymorphic behaviour".
For example:
class BaseButton
{
virtual void onclick() {/*implement here or declare pure virtual*/}
};
class RedButton: public BaseButton /* overrides only onclick */
{
void onclick() override { /*specific implementation for Red Buttons */}
};
class ShinyRedButton: public RedButton /* overrides only onclick */
{
void onclick() override { /*specific implementation for Shiny Red Buttons */}
};
then use it like (C++14 smart pointers)
std::unique_ptr<BaseButton> bb = new ShinyRedButton;
bb->onclick(); // will pick up the "right" ShinyRedButton::onclick()` function
You can do this in many ways.
Using a Button class where button objects have a pointer to methods that are invoked onClick. In C you would do this using a callback and you can also do it that way in C++:
class Button {
using funType = void(void);
public:
Button(funType* callback) : function(callback) { }
void onClick() { function(); }
private:
funType* function;
};
However do take note that function pointers are error prone, can't really be inlined by the compiler, and should generally be avoided. This method also works with capture-less lambdas.
Button red([] { std::cout << "Red button\n"; });
Button green(&green_button_function);
Creating different Button objects with different onClick methods on the fly. C++ has a mechanism to do this called templates:
template <class Fun>
class Button {
public:
Button(Fun f) : functor(f) { }
void onClick() { functor(); }
private:
Fun functor;
};
template <class Fun>
Button<Fun> make_button(Fun f) { return Button<Fun>(f); }
I am omitting details such as references on purpose here.
You could then use the Button class with callbacks as well as lambdas in the following way:
auto green = make_button([] { std::cout << "Green button pressed!\n"; });
auto red = make_button(&red_button_function);
You need to use auto with this method because otherwise you would have to specify the type of the functionality by hand, which is not possible e.g. for lambda objects.
Using polymorphism as shown by vsoftco, where you create separate classes for each Button functionality. Or you can make a ButtonAction abstract class to which Button has a reference. Then you implement different functionalities in different classes, but stay with one Button class. This is known as the strategy pattern:
class ButtonAction {
public:
virtual void onClick() = 0;
};
class Button {
public:
Button(std::unique_ptr<ButtonAction> action) :
action_(std::move(action)) {}
void onClick() { action_->onClick(); }
private:
std::unique_ptr<ButtonAction> action_;
};
class RedButtonAction : public ButtonAction {
void onClick() override { red(); }
};
class GreenButtonAction : public ButtonAction {
void onClick() override { green(); }
};
Using this method requires constructing Buttons from ButtonAction unique_ptrs
Button red(std::unique_ptr<ButtonAction>(new RedButtonAction));
Button green(std::unique_ptr<ButtonAction>(new GreenButtonAction));
You're right in that, if each button is fundamentally the same but needs different event handlers bound to it, implementing a new type for each one is not quite right.
Instead your Button type would have a member function that allows users to "attach" an event handler, and a member function to invoke it.
class Button
{
public:
Button()
: onClickHandler()
{}
void setOnClickHandler(std::function<void()> callback)
{
onClickHandler = callback;
}
friend class UI;
private:
void onClick()
{
onClickHandler();
}
std::function<void()> onClickHandler;
};
Then your user does:
void foo()
{
std::cout << "Some buttons do this!\n";
}
Button btn;
btn.setOnClickHandler(foo);
And your program's internals will set up things such that your window manager (above I've assumed that it's some class called UI) invokes btn.onClick() for you, which, since you "attached" foo, will end up invoking foo.
(In modern C++ you'd probably make use of lambda functions to tidy this up, but the above is a simple example to showcase the general design idea.)
In this way, you can attach different handlers to different Button instances, but the Button interface itself is stable.
This is similar to how, for example, you manipulate the DOM in JavaScript.
Using a std::function is the key here. You will have the virtual call overheard and potential memory allocation if your callable (lambda, function, member function) is large. This achieves your requirements of a single type executing different callbacks without defining an class inheritance. Also using uniform initialization makes it very convenient to construct Button class with a lambda without manually creating a constructor.
Live example:
http://coliru.stacked-crooked.com/a/f9007c3f103f3ffe
#include <functional>
#include <vector>
using namespace std;
struct Button
{
function<void()> OnClick;
};
int main()
{
vector<Button> buttons =
{
{[] { printf("Button0::OnClick()\n"); }},
{[] { printf("Button1::OnClick()\n"); }},
{[] { printf("Button2::OnClick()\n"); }},
};
for(auto&& button : buttons)
button.OnClick();
}
Your Agui library supports a signaling system, with the member function addActionListener.
This allows you to derive a class from agui::ActionListener to perform the specific task intended for one or more buttons:
class SimpleActionListener : public agui::ActionListener
{
public:
virtual void actionPerformed(const agui::ActionEvent &evt)
{
std::cout << "Button pushed" << std::endl;
}
};
The object above can be attached to a button's "press" action with:
SimpleActionListener simpleAL;
button1.addActionListener(&simpleAL);

How can I access a dialog item in MFC from another class?

I'm trying to access a dialog item from a function that is not in the same class as the dialog class. How can I do that?
Example:
class AnotherClass : CClas
{
AnotherClass();
public:
void MyFunction();
};
void AnotherClass::MyFunction() //Message overwriting, can't change parameters
{
CClass* temp = (CClass*)GetDlgItem(IDC_ID); //Reference to dialog item IDC_ID
temp->DoSomething(); //This gives me an assertion error
}
I know I can use "this" if it is the same dialog item than the message, but I want to access another dialog item.
Thanks for your attention.
Solution:
As suggested by Moo-Juice, you can simply pass the dialog when you instantiate the class. In my case, I couldn't do that. For some reason subclassing didn't work that way. If you face the same issue when doing an application in MFC , you can create a pointer to a CDialog and pass it your main dialog at OnInitDialog():
Example (Class):
class AnotherClass : CClass
{
AnotherClass();
public:
void MyFunction();
CDialog * mainDialog;
};
void AnotherClass::MyFunction() //Message overwriting, can't change parameters
{
CClass* temp = (CClass*)mainDialog->GetDlgItem(IDC_ID); //Reference to dialog item IDC_ID
temp->DoSomething(); //This gives me an assertion error
}
Example (OnInitDialog()):
MyMainDialog::OnInitDialog()
{
...
AnotherClass obj; //Instantiate class
obj->mainDialog = this;
return true;
}
In this example simply passing it as a parameter when creating the object makes more sense. It just didn't work with me for what I was doing.
Hope it helps anyone with a similar question.
When you instantiate AnotherClass, pass it the dialog class:
class AnotherClass
{
private:
CDialog& dialog_;
public:
AnotherClass(CDialog& dialog) : dialog_(dialog) { }
void MyFunction();
};
void AnotherClass::MyFunction()
{
CClass* temp = (CClass*)dialog_.GetDigItem(IDC_ID);
temp->doSOmething();
}

Stack of class member functions but the class isn't known yet

I have something a little tricky to explain so I'll try my best. I have an InstructionScreen class that displays arrows & blocks of text that explain what each buttons does & etc. So in InstructionScreen I have a stack of member functions each of those functions will create some arrows & text to explain what a different button does.
The InstructionScreen will be subclassed into MenuInstructScreen, OptionsInstructScreen & etc. and in these classes I will create custom functions that will create arrows & text to explain their screens buttons.
The problem is declaring this stack in InstructionScreen because it will contain functions that are part of their subclass. I am thinking I can do this, but I use templates right?
So the problem in a nutshell is how do I declare a stack that will contain member functions of a class that doesn't exist yet?
The problem is a lot easier to understand & see if you look at this simple example:
typedef class InstructionScreen;
typedef class MenuInstructScreen;
template <typename FooClass>
typedef void (FooClass::*MemberFuncPtr)(); // will be typedef void (MenuInstructScreen::*MemberFuncPtr)();
class InstructionScreen
{
public:
InstructionScreen() {}
void runInstructions()
{
while ( !instructionStep.empty() )
{
(this->*instructionStep.top())();
instructionStep.pop();
}
}
protected:
stack <MemberFuncPtr> instructionStep;
};
class MenuInstructScreen : public InstructionScreen
{
public:
MenuInstructScreen()
{
// Set instruction schedule
instructionStep.push( &MenuInstructScreen::step2() );
instructionStep.push( &MenuInstructScreen::step1() );
}
void step1()
{
// create some widgets that point to buttons & widgets that contain text instructions
}
void step2()
{
// create some widgets that point to buttons & widgets that contain text instructions
}
private:
};
class OptionsInstructScreen : public InstructionScreen
{
public:
OptionsInstructScreen()
{
// Set instruction schedule
instructionStep.push( &OptionsInstructScreen::step2() );
instructionStep.push( &OptionsInstructScreen::step1() );
}
void step1()
{
// create some widgets that point to buttons & widgets that contain text instructions
}
void step2()
{
// create some widgets that point to buttons & widgets that contain text instructions
}
private:
};
C++ doesn't allow templated typedefs, but C++11 supports this via Template Aliases. If you don't have C++11 support in your compiler, you could achieve the same by using a functor such as Boost.Function.
typedef boost::function<void()> Func;
Since your typedef is for member functions that take no arguments, you could use the aboce to define a functor that returns void and accepts no arguments. Although it wouldn't be restricted to members of a specific class. You would push items onto your stack in derived classes using something like:
stack.push(boost::bind(&MenuInstructScreen::step2, this));
stack.push(boost::bind(&MenuInstructScreen::step1, this));
Your original example would now look something like this...
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <stack>
class InstructionScreen
{
public:
void runInstructions()
{
while (!instructionStep.empty())
{
boost::function<void()> func = instructionStep.top();
instructionStep.pop();
func();
}
}
protected:
std::stack<boost::function<void()> > instructionStep;
};
class MenuInstructScreen : public InstructionScreen
{
public:
MenuInstructScreen()
{
instructionStep.push(boost::bind(&MenuInstructScreen::step2, this));
instructionStep.push(boost::bind(&MenuInstructScreen::step1, this));
}
void step1()
{
//
}
void step2()
{
//
}
};
class OptionsInstructScreen : public InstructionScreen
{
public:
OptionsInstructScreen()
{
instructionStep.push(boost::bind(&OptionsInstructScreen::step2, this));
instructionStep.push(boost::bind(&OptionsInstructScreen::step1, this));
}
void step1()
{
//
}
void step2()
{
//
}
private:
};
int main() { }
There are no "template typedef"s in C++. In C++0x you can use template aliases, but support for that is limited at the moment.
Why not simply add a virtual function to your base class:
virtual void steps() { };
Then let each derived class implement it:
void steps() { step1(); step2(); }
Then you can store pointers-to-base-class in your stack and just call ->steps().