How to implement the observer pattern safely? - c++

I'm implementing a mechanism similar to the observer design pattern for a multithreaded Tetris game. There is a Game class which contains a collection of EventHandler objects. If a class wants to register itself as a listener to a Game object it must inherit the Game::EventHandler class. On state change events a corresponing method is called on the EventHandler interface of each listener. This is what the code looks like:
class Game
{
public:
class EventHandler
{
public:
EventHandler();
virtual ~EventHandler();
virtual void onGameStateChanged(Game * inGame) = 0;
virtual void onLinesCleared(Game * inGame, int inLineCount) = 0;
private:
EventHandler(const EventHandler&);
EventHandler& operator=(const EventHandler&);
};
static void RegisterEventHandler(ThreadSafe<Game> inGame, EventHandler * inEventHandler);
static void UnregisterEventHandler(ThreadSafe<Game> inGame, EventHandler * inEventHandler);
typedef std::set<EventHandler*> EventHandlers;
EventHandlers mEventHandlers;
private:
typedef std::set<Game*> Instances;
static Instances sInstances;
};
void Game::RegisterEventHandler(ThreadSafe<Game> inGame, EventHandler * inEventHandler)
{
ScopedReaderAndWriter<Game> rwgame(inGame);
Game * game(rwgame.get());
if (sInstances.find(game) == sInstances.end())
{
LogWarning("Game::RegisterEventHandler: This game object does not exist!");
return;
}
game->mEventHandlers.insert(inEventHandler);
}
void Game::UnregisterEventHandler(ThreadSafe<Game> inGame, EventHandler * inEventHandler)
{
ScopedReaderAndWriter<Game> rwgame(inGame);
Game * game(rwgame.get());
if (sInstances.find(game) == sInstances.end())
{
LogWarning("Game::UnregisterEventHandler: The game object no longer exists!");
return;
}
game->mEventHandlers.erase(inEventHandler);
}
There are two problems that I often experience with this kind of pattern:
A listener object wants to unregister itself on an already deleted object resulting in a crash.
A event is fired to a listener that no longer exists. This happens most often in multithreaded code. Here's a typical scenario:
The game state changes in a worker thread. We want the notification to occur in the main thread.
The event is wrapped in a boost::function and sent as a PostMessage to the main thread.
A short time later this function object is processed by the main thread while the Game object is already deleted. The result is a crash.
My current workaround is the one that you can see in above code sample. I made the UnregisterEventHandler a static method which checks against a list of instances. This does help, but I find it a somewhat hackish solution.
Does anyone know of a set of guidelines on how to cleanly and safely implement notifier/listener system? Any advice on how to avoid the above pitfalls?
PS: If you need more information in order to answer this question you can find the relevant code online here: Game.h, Game.cpp, SimpleGame.h, SimpleGame.cpp, MainWindow.cpp.

The rule of thumb is that delete and new for an object should be near each other. E.g. in constructor and destructor or before and after a call where you use the object. So it's a bad practice to delete an object in another object when the latter one didn't create the former one.
I don't understand how you pack the events. It seems that you have to check whether the game is still alive before processing an event. Or you can use shared_ptr in events and other places to be sure that games are deleted last.

I write a lot of C++ code and needed to create an Observer for some game components I was working on. I needed something to distribute "start of frame", "user input", etc., as events in the game to interested parties. I had the same problem to consider...the firing of an event would lead to the destruction of another observer which may also subsequently fire. I need to handle this. I did not need to handle thread safety, but the design requirement I usually shoot for is to build something simple enough (API wise) that I can put in a few mutexes in the right place and the rest should take care of itself.
I also wanted it to be straight C++, not dependent on the platform or a specific technology (such as boost, Qt, etc.) because I often build and re-use components (and the ideas behind them) across different projects.
Here is the rough sketch of what I came up with as a solution:
The Observer is a singleton with keys (enumerated values, not strings) for Subjects to register interest in. Because it is a singleton, it always exists.
Each subject is derived from a common base class. The base class has an abstract virtual function Notify(...) which must be implemented in derived classes, and a destructor that removes it from the Observer (which it can always reach) when it is deleted.
Inside the Observer itself, if Detach(...) is called while a Notify(...) is in progress, any detached Subjects end up on a list.
When Notify(...) is called on the Observer, it creates a temporary copy of the Subject list. As it iterates over it, it compare it to the recently detached. If the target is not on it, Notify(...) is called on the target. Otherwise, it is skipped.
Notify(...) in the Observer also keeps track of the depth to handle cascading calls (A notifies B, C, D, and the D.Notify(...) triggers a Notify(...) call to E, etc.)
This is what the interface ended up looking like:
/*
The Notifier is a singleton implementation of the Subject/Observer design
pattern. Any class/instance which wishes to participate as an observer
of an event can derive from the Notified base class and register itself
with the Notiifer for enumerated events.
Notifier derived classes MUST implement the notify function, which has
a prototype of:
void Notify(const NOTIFIED_EVENT_TYPE_T& event)
This is a data object passed from the Notifier class. The structure
passed has a void* in it. There is no illusion of type safety here
and it is the responsibility of the user to ensure it is cast properly.
In most cases, it will be "NULL".
Classes derived from Notified do not need to deregister (though it may
be a good idea to do so) as the base class destrctor will attempt to
remove itself from the Notifier system automatically.
The event type is an enumeration and not a string as it is in many
"generic" notification systems. In practical use, this is for a closed
application where the messages will be known at compile time. This allows
us to increase the speed of the delivery by NOT having a
dictionary keyed lookup mechanism. Some loss of generality is implied
by this.
This class/system is NOT thread safe, but could be made so with some
mutex wrappers. It is safe to call Attach/Detach as a consequence
of calling Notify(...).
*/
class Notified;
class Notifier : public SingletonDynamic<Notifier>
{
public:
typedef enum
{
NE_MIN = 0,
NE_DEBUG_BUTTON_PRESSED = NE_MIN,
NE_DEBUG_LINE_DRAW_ADD_LINE_PIXELS,
NE_DEBUG_TOGGLE_VISIBILITY,
NE_DEBUG_MESSAGE,
NE_RESET_DRAW_CYCLE,
NE_VIEWPORT_CHANGED,
NE_MAX,
} NOTIFIED_EVENT_TYPE_T;
private:
typedef vector<NOTIFIED_EVENT_TYPE_T> NOTIFIED_EVENT_TYPE_VECTOR_T;
typedef map<Notified*,NOTIFIED_EVENT_TYPE_VECTOR_T> NOTIFIED_MAP_T;
typedef map<Notified*,NOTIFIED_EVENT_TYPE_VECTOR_T>::iterator NOTIFIED_MAP_ITER_T;
typedef vector<Notified*> NOTIFIED_VECTOR_T;
typedef vector<NOTIFIED_VECTOR_T> NOTIFIED_VECTOR_VECTOR_T;
NOTIFIED_MAP_T _notifiedMap;
NOTIFIED_VECTOR_VECTOR_T _notifiedVector;
NOTIFIED_MAP_ITER_T _mapIter;
// This vector keeps a temporary list of observers that have completely
// detached since the current "Notify(...)" operation began. This is
// to handle the problem where a Notified instance has called Detach(...)
// because of a Notify(...) call. The removed instance could be a dead
// pointer, so don't try to talk to it.
vector<Notified*> _detached;
int32 _notifyDepth;
void RemoveEvent(NOTIFIED_EVENT_TYPE_VECTOR_T& orgEventTypes, NOTIFIED_EVENT_TYPE_T eventType);
void RemoveNotified(NOTIFIED_VECTOR_T& orgNotified, Notified* observer);
public:
virtual void Reset();
virtual bool Init() { Reset(); return true; }
virtual void Shutdown() { Reset(); }
void Attach(Notified* observer, NOTIFIED_EVENT_TYPE_T eventType);
// Detach for a specific event
void Detach(Notified* observer, NOTIFIED_EVENT_TYPE_T eventType);
// Detach for ALL events
void Detach(Notified* observer);
/* The design of this interface is very specific. I could
* create a class to hold all the event data and then the
* method would just have take that object. But then I would
* have to search for every place in the code that created an
* object to be used and make sure it updated the passed in
* object when a member is added to it. This way, a break
* occurs at compile time that must be addressed.
*/
void Notify(NOTIFIED_EVENT_TYPE_T, const void* eventData = NULL);
/* Used for CPPUnit. Could create a Mock...maybe...but this seems
* like it will get the job done with minimal fuss. For now.
*/
// Return all events that this object is registered for.
vector<NOTIFIED_EVENT_TYPE_T> GetEvents(Notified* observer);
// Return all objects registered for this event.
vector<Notified*> GetNotified(NOTIFIED_EVENT_TYPE_T event);
};
/* This is the base class for anything that can receive notifications.
*/
class Notified
{
public:
virtual void Notify(Notifier::NOTIFIED_EVENT_TYPE_T eventType, const void* eventData) = 0;
virtual ~Notified();
};
typedef Notifier::NOTIFIED_EVENT_TYPE_T NOTIFIED_EVENT_TYPE_T;
NOTE: The Notified class has a single function, Notify(...) here. Because the void* is not type safe, I created other versions where notify looks like:
virtual void Notify(Notifier::NOTIFIED_EVENT_TYPE_T eventType, int value);
virtual void Notify(Notifier::NOTIFIED_EVENT_TYPE_T eventType, const string& str);
Corresponding Notify(...) methods were added to the Notifier itself. All these used a single function to get the "target list" then called the appropriate function on the targets. This works well and keeps the receiver from having to do ugly casts.
This seems to work well. The solution is posted on the web here along with the source code. This is a relatively new design, so any feedback is greatly appreciated.

Related

How can I reduce coupling in my Event Bus implementation

In my application, I have several modules that don't fit an 'is-a' or 'has-a' relationship, but still need to communicate and pass data to each other. To try and loosely couple these modules, I've implemented an Event Bus class that handles message passing from 'event posters' to 'event listeners'.
Classes can implement IEventListener if they wish to register to receive certain events. Likewise, classes can call EventBus::postEvent() if they need to push an event out to the bus. When EventBus::update() is called EventBus processes the queue of scheduled messages and routes them to registered listeners.
EventBus.h
#pragma once
#include <queue>
#include <map>
#include <set>
#include <memory>
class IEvent
{
public:
static enum EventType
{
EV_ENEMY_DIED,
EV_ENEMY_SPAWNED,
EV_GAME_OVER
};
virtual ~IEvent() {};
virtual EventType getType() const = 0;
};
class IEventListener
{
public:
virtual void handleEvent(IEvent * const e) = 0;
};
class EventBus
{
public:
EventBus() {};
~EventBus() {};
void update();
void postEvent(std::unique_ptr<IEvent> &e);
void registerListener(IEvent::EventType t, IEventListener *l);
void removeListener(IEvent::EventType t, IEventListener *l);
private:
std::queue<std::unique_ptr<IEvent>> m_eventBus;
std::map<IEvent::EventType, std::set<IEventListener *>> m_routingTable;
};
EventBus.cpp
#include "EventBus.h"
using namespace std;
/**
* Gives the EventBus a chance to dispatch and route events
* Listener callbacks will be called from here
*/
void EventBus::update()
{
while (!m_eventBus.empty())
{
// Get the next event (e_local now owns the on-heap event object)
unique_ptr<IEvent> e_local(move(m_eventBus.front()));
m_eventBus.pop();
IEvent::EventType t = e_local->getType();
auto it = m_routingTable.find(t);
if (it != m_routingTable.end())
{
for (auto l : ((*it).second))
{
l->handleEvent(e_local.get());
}
}
}
}
/**
* Posts an event to the bus, for processing and dispatch later on
* NB: The event bus will takes ownership of the on-heap event here
*/
void EventBus::postEvent(unique_ptr<IEvent> &e)
{
// The EventBus now owns the object pointed to by e
m_eventBus.push(unique_ptr<IEvent>(move(e)));
}
/**
* Registers a listener against an event type
*/
void EventBus::registerListener(IEvent::EventType t, IEventListener *l)
{
// Add this listener entry
// If the routing table doesn't have an entry for t, std::map.operator[] will add one
// If the listener is alredy registered std::set.insert() won't do anything
m_routingTable[t].insert(l);
}
/**
* Removes a listener from the event routing table
*/
void EventBus::removeListener(IEvent::EventType t, IEventListener *l)
{
// Check if an entry for event t exists
auto keyIterator = m_routingTable.find(t);
if (keyIterator != m_routingTable.end())
{
// Remove the given listener if it exists in the set
m_routingTable[t].erase(l);
}
}
As you can see, in my current implementation, I create concrete IEvent implementations for every type of event I want to pass around. I did this so that each event can have custom data attached to it (a requirement for my situation). Unfortunately, this means my EventBus system has to know about all the users of the system, increasing the coupling between my EventBus class and the users of the class. Additionally, the IEvent interface needs to hold a list of all event types as an enum, which has the same problem (increased coupling).
Is there a way to modify this implementation so that EventBus can be totally generic (doesn't need to know about the users of the EventBus), and yet still allow me to pass custom data with each event? I looked into C++11 variadic template functions but couldn't figure out how to use them in this case.
As a side-question, am I using std::unique_ptr correctly here?
Question 1 "Is there a way to modify this implementation so that EventBus can be totally generic":
Short answer, yes.
Longer answer: There are many ways of accomplishing this. One is described here:
Both the producer and the consumer of the event needs to agree on the type/data but the EventBus itself does not need to know. One way of accomplishing this could be to use boost::signals2::signal<T> as the event type. This will give you a proven, flexible and type safe signal/slot implementation. What it will not provide, however, is the possibility to queue up slot callbacks and process them from the EventBus::update()-function.
But, that can also be remedied. By making the event type EventBus::postEvent() takes as a parameter be std::function<void()> and calling postEvent() like this:
boost::signals2::signal<int> signal;
...
eventbus.postEvent(boost::bind(signal, 42));
// note: we need to use boost::bind (not std::bind) for boost::signals to be happy
The EventBus will see a std::function<void()> and dispatch to the slot. The data (42 in this example) will be kept by the result of boost::bind and be used as the parameter when the slot is called.
Question 2 "Am I using std::unique_ptr correctly":
Almost. I would drop the reference of EventBus::postEvent making it:
void EventBus::postEvent(std::unique_ptr<IEvent> e);
By doing this, you force the caller to actively move the std::unique_ptr<IEvent> into the EventBus. This will make the user aware the EventBus takes ownership and also making it obvious to people reading the code what the intent is and how ownership is transferred.
CppCoreGuidelines R.32:
"Take a unique_ptr parameter to express that a function assumes ownership of a widget"

Handling events raised from a lower level object

I'm writing a C++ programm using GTK+3.0. Anyway, I think this question may apply to any framework that uses events / signals.
I have a container class, say containerClass and a child class, say childClass. A childClass object child is contained inside a containerClass object container.
The child object is written to modify properties of something. To this aim, it has GtkEntry, GtkButton and so on. When I click the "save button", an event is raised.
This event must be handled by the container object, because the container is interfaced with a database in someway.
Hereafter, you find the solution I'm using to do the job:
// Child class
class childClass {
void setClickHandler_External(void (*extFun)(string property), void *);
void (*clickHandler_External)(string, void *);
void *clickHandler_External_Data;
static void buttonClicked(GtkWidget *widget, void *data);
}
void childClass::setClickHandler_External(void (*extFun)(string), void *data) {
// Set the external event handler
clickHandler_External = extFun;
clickHandler_External_Data = data;
}
void childClass::buttonClicked(GtkWidget *widget, void *data) {
childClass *m = (childClass *)data;
// Call the external event handler
m->clickHandler_External(property, m->clickHandler_External_Data);
}
// Container Class
class containerClass {
childClass child;
static void clickHandler(string property, void *data);
}
containerClass::containerClass() {
// Set the event handler
child.setClickHandler_External((void(*)(string))&(this->clickHandler), (void *)this);
}
void containerClass::clickHandler(string property, void *data) {
// Event handler in the upper class
containerClass *m = (containerClass *)data;
//FINALLY, DO THE JOB WITH PROPERTY!!!
}
This works well and does the job. Anyway, I was wondering if there is a smarter and cleaner way to achieve the same aim, maybe without using pointers to static functions, or by defining some kind of pattern to be reused everytime I need to have the same mechanism.
Thanks in advance
Gtkmm uses the sigc++ library to take care of all of this for you. There is no need to write it yourself.
Documentation links:
Signals overview
Appendix with detailed information
So, in this case, I would use something like
button.signal_clicked().connect(sigc::mem_fun(container, &containerClass::clickHandler));
while making sure that containerClass::clickHander has the appropriate number of arguments.
My first suggestion would be to use use templates to improve the type safety of what you are doing:
template< class ParamType >
void childClass::setClickHandler_External(void (*extFun)(string, ParamType *),
ParamType *data)
{
// Set the external event handler
clickHandler_External = (void ()(string,void*))extFun;
clickHandler_External_Data = (void*)data;
}
Then you can simplify the containerClass implementation as such:
// Container Class
class containerClass {
childClass child;
static void clickHandler(string property, containerClass *data);
}
containerClass::containerClass() {
// Set the event handler
child.setClickHandler_External(&containerClass::clickHandler, this);
}
void containerClass::clickHandler(string property, containerClass *data) {
//FINALLY, DO THE JOB WITH PROPERTY!!!
}
While it's great that this cleans up the implementation, removing the explicit casting from all the container implementors, that's not really the point. The point is to prevent you from passing wrong pointers into setClickHandler_External, causing crashes on the back end when events get dispatched.
My next step would take us further from your implementation, but would require more details about what you are actually doing. Depending on your needs that would be looking into:
Inheritance: should containerClass derive from childClass? That would provide access to a virtual function table that we could override.
Functors: look at boost::function and boost::bind to implement functors, eliminating the intermediate static function call.
Lambda Functions: bleeding edge (C++11 or later), but may be a good fit for this kind of forwarding function.

How can I provide feedback from a non-Qt C++ library class to a Qt GUI?

I am developing a C++ class library for some computing-intensive tasks (machine vision).
// I am a part of a Qt-agnostic library
class Cruncher
{
/* ... */
public:
void doStuff();
};
Then there's a Qt GUI using that library. I'm creating a worker thread to call the heavy-lifting routines from the library:
// I am a part of a Qt-based GUI which utilizes the library
class Worker : public QThread
{
/* ... */
protected:
virtual void run()
{
/* ... */
Cruncher c;
for (int i = 0; i < count; ++i)
c.doStuff(); // takes some time, and while it's working
// it should communicate status changes which should
// become visible in the GUI
}
};
Now inside doStuff() a lot happens and I want to provide some feedback to the user on what is going on without waiting for doStuff() to return. For one, maybe some finer progress reporting than just increasing the meter by one step after a each call to doStuff(). Also, doStuff() may encounter non-critical failures which let it continue a part of the work, but I'd like a message to appear in the GUI when this happens as Cruncher is working (and Worker is currently busy with a call to doStuff()).
I want the library to remain Qt-independent so I'm not willing to add signals and slots to Cruncher. Any other way to enable it to provide feedback to the GUI to report on its work when it's not a Qt class?
I was considering creating a QTimer which would poll some "status" and "errorMsg" members of Cruncher at fixed intervals while Worker is running, but this seems highly sub-optimal.
I am posting my own answer because though I took #Nim's advice, I'd like the answer to be a little more verbose and hence more useful if someone should have the same problem.
I created the skeleton of a message dispatcher in the library:
// doesn't need to know about Qt
class MessagePort
{
public:
virtual void message(std::string msg) = 0;
};
Next, I added a handle to this object to Cruncher and spiced doStuff() with occasional calls to message():
// now with Super Cow powers!
class Cruncher
{
protected:
MessagePort *msgPort_;
public:
Cruncher(MessagePort *msgPort) : msgPort_(msgPort) {}
void doStuff()
{
while(...)
{
/*...*/
msgPort_->message("Foo caused an overload in Bar!");
}
}
};
Finally, I crafted an implementation of MessagePort inside the GUI using all necessary Qt goodness:
class CruncherMsgCallback : public QObject, public MessagePort
{
Q_OBJECT
public:
CruncherMsgCallback() : QObject(), MessagePort()
{
connect(this, SIGNAL(messageSignal(const QString &)),
GUI, SLOT(messageShow(const QString &)),
Qt::QueuedConnection);
}
virtual void message(std::string msg)
{
emit messageSignal(QString::fromStdString(msg));
}
signals:
void messageSignal(const QString &msg);
};
Finally when the Worker creates an instance of Cruncher, it also gives it a pointer to a working MessagePort:
class Worker
{
protected:
virtual void run()
{
CruncherMsgCallback msgC;
Cruncher c(&msgC); // &msgC works as a pointer to a
// generic MessagePort by upcasting
c.doStuff(); // Cruncher can send messages to the GUI
// from inside doStuff()
}
};
Use a callback function (class) etc, and pass that in during construction. Things you need to report, report via that callback.
You can safely emit signals from the run() method, I think that's the best way to pass information from worker thread to the main thread. Just add the signals to your QThread subclass (avoid adding slots, if you're at all unsure how QThread threading works).
Better make the connections from these signals explicitly queued, to avoid problems. Though the default, automatic connection type should also work and do Queued signal emit, but I think it's better to be explicit in cases like this. Actually also direct signals should work as such, but then you have to take care of thread safety yourself instead of letting Qt handle it for you, and you can't connect to slots which use any of the QtGui classes which only work in the main thread, so it's better to stick to queued connections.
To pass simple information to the run() method, and if immediate reaction is not needed, maybe use a few shared QAtomicInt variables or something like that as flags, which the worker thread checks when convenient. Slightly more complex method, still requiring polling, is to have shared data structure which you protect with mutex. More complex way of communicating to that direction would involve some kind of message queue (just like Qt uses in the event loop of the main thread, when you emit signal to that direction).

What are the principles of an event system in C++?

First of all, I know there are excellent implementations (Qt, Boost, cpp-event, etc.), but I ask the question because I want to know how it works !
If I understand correctly, the "event system" uses the Observer pattern : some objects are observing, waiting for something to happen... and some others send signals. All right.
So, let's say I've got my observer class, with this kind of thing :
void Observer::getNotified()
{
// Do stuff
}
My question is : how to manage dynamically what kind of stuff should be done ? I've seen a lot of people saying specifically not to use functions pointers. For my current need, I can do a switch statement, a enum type, and select different behaviors, but that's not very satisfying. So, if it's not functions pointers, how is it done ?
There is a lot of different implementations possible (whatever the language), but the abstract idea is :
have an event type identifier to know wich events have been fired by the observed object (it can be whatever works);
have a list of observers (or several, one by event type?) registered in the registered objects - that suppose that the observers are functors (function pointer or object that act like a function) or are objects with a known interface (with a virtual method to call ion event fired);
when an event is fired (by calling a function on the observed object) we just go through the list of observers registered for the event's type and pass the event information (id plus maybe data ) to the observer to be processed;
Here is a simplist implementation :
enum EventType
{
Event_A,
Event_B,
};
class Observer // for this example i'll suppose observer inherits this class
{
virtual void catchEvent( EventType e ) = 0; // for sake of the example I just need the event type, not the data, but it's often required
virtual ~Observer(){}; // virtual base classes require this to work fine.
};
class Observed
{
typedef std::vector<Observer*> ObserverList;
typedef std::map< EventType, ObserverList > ObserversTable;
ObserversTable m_observers; // we have observers for each event type
public:
void addObserver( Observer& observer, EventType eType )
{ m_observers[ eType ].push_back( observer ); } // this is simplist, to say the least...
void sendEvent( EventType event ) // here we send the event, it will be catched by observers
{ // note : often this type of system is "buffered", but here we will process it immediatly as it's a simple example
ObserverList& observers = m_observers[ event ];
for ( ObserverList::iterator it = observers.begin(); it != observers.end(); ++it )
{
Observer* observer = *it;
observer->catchEvent( event ); // here an observer receive the event
}
}
};
It's really a basic example but that might help you understand the idea.
See this rather excellent article from Pete Goodliffe, which routes to different methods depending on the event type being notified.
If you need to choose actions within a single event type, then typically your code would choose depending on the data passed in the notification.

C++: indirect invocation of `delete this` in event driven system (e.g. in GUI application)

I was working for a while with different C++ GUI frameworks (e.g. Qt, wxWidgets, also some proprietary) but cannot decide for myself regarding the topic described below.
As discussed in several questions/answers here, direct use of delete this is valid in C++ (as long as you don't dereference this any more), but it is in most cases not good idea.
But in some cases, object invokes its destructor indirectly. This situation specifically often arise in event drive systems (GUI applications come to mind first).
class Kernel {
public:
void Start() {
_window = new Window();
}
void OnCloseButton() {
if (_window) {
_window->Close();
delete _window;
_window = NULL;
}
private:
MyWindow * _window;
};
class MyWindow
{
public:
MyWindow(Kernel & kernel) : _kernel(&kernel) {
Connect(my_button_close_event, this, OnCloseButtonClicked);
}
OnCloseButtonClicked() {
// This call actually calls destructor of this object.
_kernel->OnCloseButton();
// If we access any fields of Window here, we're going to have problems
}
private:
Kernel * _kernel;
};
Notice: I did not try to compile the code - it may have typos or bad practices. But it should illustrate the idea.
So, the question is: Is it OK to do something like in the example above: the handler of the event calls some other function (method of its owner), which indirectly deletes this?
Or should I better make the Kernel class event aware and connect the event from the button directly to the method in the Kernel and then we do not have this situation of indirect call to delete this.
Thanks in advance.
It's possible to do so since the Window instance is created by the Start() method but it's a bad practice in Object Oriented Programming.