How to pass pointer to a member within class to outer class? - c++

I am trying to pass a pointer to memeber of class(Dialog::handler) from its method(in scope of Dialog::render) to some outer method(Button::OnClick).
Here is a small example:
class Button
{
public:
void OnClick(void (*handler)())
{
handler();
}
};
class Dialog
{
public:
void handler()
{
//do stuff
}
void render()
{
auto button = new Button;
//Source of problem
button->OnClick(this->*handler);
}
};
But compiler shows error:
non-standard syntax; use '&' to create a pointer to member
Also I triend other combinations, like:
this->handler.
&this.handler.
this.*handler.
etc
But obviously they failed.

You could use std::function and pass it a lambda in which you've caught this of the object you'd like to call back:
#include <functional>
#include <iostream>
class Button {
public:
void OnClick(std::function<void()> handler) {
handler();
}
};
class Dialog {
public:
void handler() {
std::cout << "Dialog::handler\n";
}
void render() {
auto button = new Button;
// a lambda catching "this" Dialog.
button->OnClick([this] { this->handler(); });
delete button; // you didn't delete your button
}
};
int main() {
Dialog d;
d.render();
}
But it looks like you should probably inherit from a common base class that has a virtual void handler() so you can pass object pointers/references around instead. A rough idea:
#include <iostream>
class VisualBase {
public:
virtual void handler() = 0;
virtual ~VisualBase() = 0;
};
VisualBase::~VisualBase() {}
class Button : public VisualBase {
public:
void handler() override {}
void OnClick(VisualBase* caller) {
caller->handler();
}
};
class Dialog : public VisualBase {
public:
void handler() override {
std::cout << "Dialog::handler\n";
}
void render() {
Button button;
button.OnClick(this);
}
};
int main() {
Dialog d;
d.render();
}

Related

Bind Memeber function to another member

I want a system where an object inside a class can call a function inside that class when assigned.
like this collider component example:
class colliderComponent
{
void Collide()
{
//call the assigned function
}
}
class object
{
public:
void collideDelegate()
{
// do something
}
public:
collidercomponent* cc;
Object()
{
cc-> //assign collide delegate to be called on Collide()
}
}
You can do this using std::function and std::bind.
Here is an example (live demo):
#include <functional>
#include <iostream>
class colliderComponent
{
public:
void Collide()
{
collideDelegate();
}
std::function<void()> collideDelegate;
};
class Object
{
public:
void collideDelegate()
{
std::cout << "collide delgate" << std::endl;
}
public:
colliderComponent* cc;
Object(colliderComponent* cc) : cc(cc)
{
cc->collideDelegate = std::bind(&Object::collideDelegate,this); //assign collide delegate to be called on Collide()
}
};
int main()
{
colliderComponent cc;
Object o(&cc);
cc.Collide();
}

Use class template as callback in C++

I was able to make the callback work without class templates. But my requirement is to implement callbacks with passing class objects which are in template form. I have written my intent in the main(), but somehow I am unable to make it work.
I cannot use boost and C++11 for my current issue. Any help would be greatly appreciated.
// TestProj.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "glb.h"
#include "Test.h"
#include <iostream>
using namespace std;
class MyCallBack
{
private:
class Callback
{
public:
virtual ~Callback() { }
virtual void call() = 0;
};
template <typename T>
class ClassCallback : public Callback
{
private:
T* object;
void (T::*callback)();
public:
ClassCallback(T* obj, void (T::*clbk)()) : object(obj), callback(clbk) {}
virtual void call() { (object->*callback)(); }
};
private:
Callback* callback;
public:
MyCallBack() : callback(NULL) { }
~MyCallBack() { delete callback; }
template <typename T>
MyCallBack(T* obj, void (T::*clbk)())
{
callback = new ClassCallback<T>(obj,clbk);
}
void operator () ()
{
callback->call();
}
};
typedef enum {
EVENT1 = 1,
EVENT2 = 2,
EVENT3 = 4,
EVENT4 = 8
} MyEvent_t;
template <class EventT>
class EventHandler
{
public:
virtual void on_event(EventT _event) = 0;
};
class MyHandler:public EventHandler<MyEvent_t>{
virtual void on_event(MyEvent_t _event){
switch(_event){
case EVENT1:
break;
case EVENT2:
break;
}
}
};
int _tmain(int argc, _TCHAR* argv[])
{
EventHandler<MyEvent_t> *my_handler = new MyHandler();
MyCallBack rcb(my_handler,&MyHandler<MyEvent_t>::on_event);
// to check the callback
rcb();
return 0;
}
Thanks a lot of any leads!!!
The line
MyCallBack rcb(my_handler,&MyHandler<MyEvent_t>::on_event);
is a problem since on_event takes an argument. The member function pointer expected in the constructor of MyCallBack() does not take any arguments.
The following works for me from a compile/build point of view. You'll have to figure out how to make it work for a semantic point of view.
#include <iostream>
using namespace std;
class MyCallBack
{
private:
class Callback
{
public:
virtual ~Callback() { }
virtual void call() = 0;
};
template <typename T>
class ClassCallback : public Callback
{
private:
T* object;
void (T::*callback)();
public:
ClassCallback(T* obj, void (T::*clbk)()) : object(obj), callback(clbk) {}
virtual void call() { (object->*callback)(); }
};
private:
Callback* callback;
public:
MyCallBack() : callback(NULL) { }
~MyCallBack() { delete callback; }
template <typename T>
MyCallBack(T* obj, void (T::*clbk)())
{
callback = new ClassCallback<T>(obj,clbk);
}
void operator () ()
{
callback->call();
}
};
typedef enum {
EVENT1 = 1,
EVENT2 = 2,
EVENT3 = 4,
EVENT4 = 8
} MyEvent_t;
template <class EventT>
class EventHandler
{
public:
void event() { on_event(EventT()); }
virtual void on_event(EventT _event) = 0;
};
class MyHandler:public EventHandler<MyEvent_t>{
virtual void on_event(MyEvent_t _event){
switch(_event){
case EVENT1:
break;
case EVENT2:
break;
default:
break;
}
}
};
int main(int argc, char* argv[])
{
EventHandler<MyEvent_t> *my_handler = new MyHandler();
MyCallBack rcb(my_handler,&EventHandler<MyEvent_t>::event);
// to check the callback
rcb();
return 0;
}
I think what you are trying to achive is the action pattern.
Have a look here: https://en.wikipedia.org/wiki/Command_pattern
And now to the implementation:
#include <iostream>
#include <memory>
struct Action {
virtual void execute() = 0;
};
struct SomeAction : public Action {
void execute() {
std::cout << "SomeAction" << std::endl;
}
};
struct SomeOtherAction : public Action {
void execute() {
std::cout << "SomeOtherAction" << std::endl;
}
};
class EventHandler {
std::unique_ptr<Action> action; // The unique ptr will delete action if the event handler is destroyed
public:
EventHandler() :
action(new SomeAction())
{
}
void setAction(Action* newAction) {
action = std::unique_ptr<Action>(newAction);
}
void eventCalled() {
// This function is invoked from the outside if the event happens
action->execute();
}
};
int main() {
EventHandler eventHandler;
//Some event is called
eventHandler.eventCalled(); // Output "SomeAction"
// We change the action later in time
eventHandler.setAction(new SomeOtherAction());
// Another Event gets called
eventHandler.eventCalled(); // Output "SomeOtherAction"
return 0;
}

How to refer overriden static method from parent class constructor?

So we have some class (i.e. Button) and its method which takes void function.
Also we have parent class State which has static method buttonAction used to asign
to Button instance. Problem is State's child class must have an option to override
static method buttonAction and this method must be assigned to button by parent class State constructor.
It must work something like this:
Code:
MyState st;
button.click();
Desired output:
MyState::buttonAction!
But instead I get:
State::buttonAction!
Related .cpp file:
#include <iostream>
#include <cstdio>
class Button
{
public:
void setAction(void(*foo)(void));
void click();
private:
void(*foo)(void);
};
void Button::setAction(void(*foo)(void)) { this->foo = foo; }
void Button::click() { this->foo(); }
Button button;
class State
{
public:
State();
private:
static void buttonAction();
};
State::State()
{
button.setAction(this->buttonAction); // pointer to state's buttonAction
}
void State::buttonAction()
{
printf("State::buttonAction!");
};
class MyState : State
{
private:
static void buttonAction(); // overridden buttonAction
};
void MyState::buttonAction()
{
printf("MyState::buttonAction!");
};
int main() {
MyState st;
button.click();
return 0;
}
Have MyState's constructor override it:
MyState::MyState()
{
button.setAction(&buttonAction)l
}
After the superclass initially invokes setAction() to point the callback to its own static class function, this will override it, and repoint it to MyState's static class function.

A list with the same type as the class it's contained within

I'm trying to create a simple events system, which will have many different events. So, I've tried to create an event class which allows you to register functions, taking the correct type of event, and returning a boolean.
What I want is that the method post in any subclass of Event will take that subclass rather than Event, and the functions in the list listeners in each subclass should take the correct subclass type. Here's the code I already have, which forces the function to cast to the correct event type:
events.h:
namespace events {
class Event {
public:
static const std::List<bool (*)(Event)> listeners;
void post(Event event);
}
class ExampleEvent : Event {
int eventData;
}
}
events.cpp:
namespace events {
void Event::post(Event event) {
for(int i = 0; i < listeners.size(); i++) {
if(listeners[i](event)) return;
}
}
}
Is there some way I can get this to work with subclassed events without having to do the following?
bool handleExample(Event event) {
ExampleEvent exampleEvent = (ExampleEvent)event;
std::cout << exampleEvent.eventData << std::endl;
return false;
}
// Somewhere else in the code
ExampleEvent::listeners.push_back(&handleExample);
I apologise for any incorrect code, I don't quite have the rules of the language perfect yet.
The common way is to use CRTP:
namespace events {
template<typename Derived>
class Event {
public:
static const std::list<bool (*)(Derived)> listeners;
void post(Derived event)
{
static_cast<Derived&>(*this).post(event);
}
};
class ExampleEvent : Event<ExampleEvent> {
int eventData;
void post(ExampleEvent event)
{
//implement post
}
};
}
Just use virtual functions:
namespace events {
class EventHandler {
public:
static const std::list<Event*> listeners;
void post() {
for (Event * listener : listeners) {
if (listener->post()) break;
}
}
};
class BaseEvent {
public:
virtual bool post() = 0;
virtual ~BaseEvent() {}
};
class ExampleEvent : public BaseEvent { // use public inheritance
int eventData;
public:
virtual bool post() override {
if (eventData == 0) return true;
return false;
}
};
}

Saving a function pointer in member of a class

I am making a menu bar that takes in menu items. I want the window that holds the menu bar to decide what the behaviour of a menu item will be. So I want the window to pass a function to the menu item.
My best attempt is getting me this error:
error: no matching function for call to 'MenuItem::setBehaviour(void (MyWindow::*)())'
Here is MenuItem.h:
class MenuItem{
public:
typedef void (sf::RenderWindow::*function_type)();
MenuItem(sf::RenderWindow* win); // window that holds the menu bar
void setBehaviour(function_type f); // I want to be able to change the behaviour
// to reuse the menu item
void action(); // use the function
private:
sf::RenderWindow* m_window;
function_type m_function;
};
MenuItem.cpp
MenuItem::MenuItem(sf::RenderWindow* win) : m_window(win)
{
//ctor
}
void MenuItem::setBehaviour(function_type f)
{
m_function = f;
}
void MenuItem::action()
{
(m_window->*m_function)();
}
The window that adds the menu bar:
class MyWindow : public sf::RenderWindow
{
//...
void close();
};
And the window's cpp file:
MyWindow::MyWindow() : sf::RenderWindow(...)
{
//...
MenuItem item(this);
item.setBehaviour(&MyWindow::close); // error!
//...
}
//...
void MyWindow::close()
{
this->close();
}
What you could try to solve that is to make MenuItem a templated class:
template<typename RenderWindow>
class MenuItem{
public:
typedef void (RenderWindow::*function_type)();
MenuItem::MenuItem(RenderWindow* win)
: m_window(win) {
std::static_assert(
std::is_base_of<sf::RenderWindow,RenderWindow>()
,"RenderWindow must be derived from sf::RenderWindow.");
}
void setBehaviour(function_type f) {
m_function = f;
}
void action() {
m_window->*m_function)();
}
private:
RenderWindow* m_window;
function_type m_function;
};
Omit the MenuItem.cpp file completely.
You can instantiate and access a MenuItem like
MyWindow myWindow;
MenuItem<MyWindow> closeWindow(myWindow);
menuItem.setBehavior(MyWindow::close);
// ...
menuItem.action();
then.
You could use std::function for that:
// MenuItem.h
#include <functional>
class MenuItem
{
public:
using function_type = std::function<void()>;
auto setBehaviour(function_type f) -> void;
auto action() -> void;
private:
function_type m_function;
};
// MenuItem.cpp
auto MenuItem::setBehaviour(function_type f) -> void
{
m_function = f;
}
auto MenuItem::action() -> void
{
m_function();
}
// MyWindow.cpp
#include <functional>
MyWindow::MyWindow() : sf::RenderWindow(...)
{
MenuItem item(this);
item.setBehaviour(std::bind(&MyWindow::close, this));
}
auto MyWindow::close() -> void
{
// do something
}
The two answers given were over my head a little. I spent some time looking at Jan's std::function and learned a little more in the process. Here's what I did wrong:
The functions for MenuItem will come from MyWindow, not sf::RenderWindow, so I need to forward declare MyWindow and change all the sf::RenderWindows to MyWindow.
class MyWindow; // fix: forward declaration
class MenuItem{
public:
typedef void (MyWindow::*function_type)(); // fix
MenuItem(MyWindow* win); // fix
void setBehaviour(function_type f);
void action();
private:
MyWindow* m_window; // fix
function_type m_function;
};
MenuItem.cpp
MenuItem::MenuItem(MyWindow* win) : m_window(win) // fix
{
//ctor
}