Original Post
Hi all, I'm working on an events framework for C++. I'm trying to base it as closely on C#/.NET's implementation as possible. So far, I'm quite happy with how it is turning out, but it'd be nice to receive some feedback from those who are more knowledgeable on the C++ language. Here are the classes used: Using the classes is very straightforward. Here is an example: For simplicities sake, the example only demonstrates the FunctionEventHandler variation of EventHandler. MethodEventHandler is used in the same way, except you have to specify the type and instance of the target. If anyone needs an example of this, I'll post that too. I'm still working on this. I want to add EventArgs (again, a-la .NET) and tidy a few things up. Any feedback on this work-in-progress would be welcome. :) *** Quick question: can I use a slist in the version of STL supplied with VC++? I can't seem to find it anywhere. :( Thanks!
#pragma once
#include <list>
// The base class for all event handlers
class EventHandler
{
friend class Event;
// Abstract methods
private:
virtual void Invoke(void* sender) = 0;
virtual EventHandler* Clone() = 0;
virtual bool Equals(EventHandler& other) = 0;
};
// Implements an event handler for a method of a given type
template<class TTarget>
class MethodEventHandler : public EventHandler
{
typedef void(TTarget::*methodType)(void*);
// Fields
private:
TTarget* target;
methodType method;
// Constructor
public:
MethodEventHandler(TTarget* target, methodType method)
{
this->target = target;
this->method = method;
}
// Methods
private:
void Invoke(void* sender)
{
(this->target->*(method))(sender);
}
EventHandler* Clone()
{
EventHandler* clone = new MethodEventHandler(this->target, this->method);
return clone;
}
bool Equals(EventHandler& other)
{
MethodEventHandler* evt = dynamic_cast<MethodEventHandler*>(&other);
if (evt == NULL)
{
return false;
}
else
{
return ((this->target == evt->target) && (this->method == evt->method));
}
}
};
// Implements an event handler for a function
class FunctionEventHandler : public EventHandler
{
typedef void(funcType)(void*);
// Fields
private:
funcType* func;
// Constructor
public:
FunctionEventHandler(funcType* func)
{
this->func = func;
}
// Methods
private:
void Invoke(void* sender)
{
(this->func)(sender);
}
EventHandler* Clone()
{
EventHandler* clone = new FunctionEventHandler(this->func);
return clone;
}
bool Equals(EventHandler& other)
{
FunctionEventHandler* evt = dynamic_cast<FunctionEventHandler*>(&other);
if (evt == NULL)
{
return false;
}
else
{
return (this->func == evt->func);
}
}
};
// The main event class, which allows EventHandlers to be added, removed, and for the event to be invoked
class Event
{
// Fields
private:
std::list<EventHandler*> targets;
// Constructors / Deconstructors
public:
Event()
{
}
~Event()
{
}
// Methods
private:
void Subscribe(EventHandler& evt)
{
EventHandler* evtClone = evt.Clone();
this->targets.push_back(evtClone);
}
void Unsubscribe(EventHandler& evt)
{
std::list<EventHandler*>::const_iterator iter = this->targets.begin();
while (iter != this->targets.end())
{
if ((*iter)->Equals(evt))
{
delete (*iter);
iter = this->targets.erase(iter);
}
else
{
++iter;
}
}
}
void Invoke(void* sender)
{
for (std::list<EventHandler*>::const_iterator iter = this->targets.begin(); iter != this->targets.end(); ++iter)
(*iter)->Invoke(sender);
}
// Operators
public:
Event& operator +=(EventHandler& evt)
{
this->Subscribe(evt);
return *this;
}
Event& operator -=(EventHandler& evt)
{
this->Unsubscribe(evt);
return *this;
}
void operator()(void* sender)
{
this->Invoke(sender);
}
};
#include <iostream>
#include "Events.h"
class Counter
{
// Fields
private:
int count;
// Constructor
public:
Counter()
{
this->count = 0;
}
// Methods
public:
void Increment()
{
this->count += 1;
// Determine whether a multiple of ten has been reached
int div10remainder = this->count % 10;
if (div10remainder == 0)
this->MultipleOfTen(this);
}
int GetCount()
{
return count;
}
// Events
public:
Event MultipleOfTen;
};
void Counter_MultipleOfTen(void* sender)
{
// Get a pointer to the counter that invoked the event
Counter* counter = (Counter*)sender;
// Output the count
std::cout << "Multiple of ten found : " << counter->GetCount() << std::endl;
}
int main()
{
// Create a counter
Counter counter = Counter();
// Add an event handler for the 'MultipleOfTen' event
counter.MultipleOfTen += FunctionEventHandler(Counter_MultipleOfTen);
// Count to a hundred
for (int i = 0; i < 100; ++i)
counter.Increment();
// Remove the event handler
counter.MultipleOfTen -= FunctionEventHandler(Counter_MultipleOfTen);
// Wait for key press
std::cin.get();
}