I am trying to make a very simple event system for learning purposes, after seeing some much more complicated code on the internet I was wondering if what I am doing is fine of if it has major issues. The code works but I am not sure if it is fast and safe.
The part that worries me is that in my test Listener class (KeyListener) I have to do a cast in order to get the correct Event, is this considered bad practice?
Thanks for your help!
Here is the code:
Event.h
extern unsigned int NULL_EVENT;
extern unsigned int KEY_PRESSED_EVENT;
extern unsigned int EVENT_AMOUNT;
class Event
{
public:
Event();
Event(const Event&);
Event& operator=(const Event&);
virtual unsigned int getType() const;
};
Listener.h:
class Listener
{
public:
Listener();
Listener(const Listener&);
Listener& operator=(const Listener&);
virtual unsigned int getEventType() const;
virtual void onEvent(Event*);
};
EventHandler.h:
class EventHandler
{
private:
LinkedList<Listener*>* listeners;
void deleteData();
public:
EventHandler();
EventHandler(const EventHandler&);
EventHandler& operator=(const EventHandler&);
~EventHandler();
void registerListener(Listener*);
void onEvent(Event&);
};
EventHandler.cpp:
EventHandler::EventHandler()
{
listeners = new LinkedList<Listener*>[EVENT_AMOUNT];
}
EventHandler::EventHandler(const EventHandler& handler)
{
listeners = new LinkedList<Listener*>[EVENT_AMOUNT];
for(unsigned int i=0;i<EVENT_AMOUNT;i++)
{
*(listeners + i) = *(handler.listeners + i);
}
}
EventHandler& EventHandler::operator=(const EventHandler& handler)
{
deleteData();
listeners = new LinkedList<Listener*>[EVENT_AMOUNT];
for(unsigned int i=0;i<EVENT_AMOUNT;i++)
{
*(listeners + i) = *(handler.listeners + i);
}
return *this;
}
EventHandler::~EventHandler()
{
deleteData();
}
void EventHandler::deleteData()
{
delete[] listeners;
}
void EventHandler::registerListener(Listener* listener)
{
unsigned int id = listener->getEventType();
assert(id < EVENT_AMOUNT && "Event type is out of bounds!");
if(!(listeners + id)->contains(listener))
{
std::cout << "registering listener of id: " << id << std::endl;
(listeners + id)->add(listener);
}
}
void EventHandler::onEvent(Event& event)
{
unsigned int id = event.getType();
assert(id < EVENT_AMOUNT && "Event type is out of bounds!");
LinkedListIterator<Listener*> itt = (listeners + id)->getIterator();
for(;itt.isValid();itt.next())
{
itt.getElement()->onEvent(&event);
}
}
Here is test Event and a test Listener: KeyPressedEvent.h:
class KeyPressedEvent : public Event
{
protected:
unsigned int keyCode;
public:
KeyPressedEvent(unsigned int);
KeyPressedEvent(const KeyPressedEvent&);
KeyPressedEvent& operator=(const KeyPressedEvent&);
unsigned int getKeyCode() const;
virtual unsigned int getType() const override;
};
KeyPressedEvent.cpp
KeyPressedEvent::KeyPressedEvent(unsigned int keyCode)
{
this->keyCode = keyCode;
}
KeyPressedEvent::KeyPressedEvent(const KeyPressedEvent& event)
{
keyCode = event.keyCode;
}
KeyPressedEvent& KeyPressedEvent::operator=(const KeyPressedEvent& event)
{
keyCode = event.keyCode;
return *this;
}
unsigned int KeyPressedEvent::getKeyCode() const
{
return keyCode;
}
unsigned int KeyPressedEvent::getType() const
{
return KEY_PRESSED_EVENT;
}
KeyListener.h:
class KeyListener : public Listener
{
public:
KeyListener();
virtual unsigned int getEventType() const override;
virtual void onEvent(Event*) override;
};
KeyListener.cpp:
KeyListener::KeyListener()
{
}
unsigned int KeyListener::getEventType() const
{
return KEY_PRESSED_EVENT;
}
void KeyListener::onEvent(Event* e)
{
KeyPressedEvent* event = (KeyPressedEvent*)e; //Even though I am sure that this is the correct event type, can I do things like this or is this considered bad practice?
std::cout << "key pressed: " << event->getKeyCode() << std::endl;
}
main.cpp:
EventHandler handler;
KeyListener listener;
handler.registerListener(&listener);
KeyPressedEvent event(5);
handler.onEvent(event);
~~~
(and possibly a language hint) instead of prefixing each line with another 4 blanks. \$\endgroup\$