对于一个项目,我需要一个观察者类(由一个主题拥有,然后通知其所有观察者)来处理其他行为。 这些观察者通过调用 onNotify(Event*) 方法来工作,然后该方法根据观察者的类型执行一些行为。 该方法的工作原理如下:
void SpecificObserver::onNotify( const Event* nevent )
{
switch (nevent->GetId())
{
case EventId::Eventtype1:
{
const Eventtype1* type1 = dynamic_cast<const Eventtype1*>(nevent);
//some behaviour...
}
break;
case EventId::Eventtype2:
{
const Eventtype2* type2 = dynamic_cast<const Eventtype2*>(nevent);
//some other behaviour...
}
break;
}
}
因此,该方法获取一个指向基本事件的指针,该事件只有 GetId() 方法,没有任何信息,并且根据该 ID,我们知道该事件是什么类型,并且我们可以转换为该事件,从而解锁它拥有的其他信息.
现在的编码是这样的:
enum class EventId{ Event, Eventtype1, Eventtype2 };
class Event
{
public:
virtual EventId GetId() const { return EventId::Event; }
};
正如您所注意到的,我必须在事件本身之前定义每种类型的事件,因此如果我想添加新类型的事件,我必须编辑事件代码。
我的问题是: 有没有办法只拥有一个
enum class EventId{ };
然后我们可以将元素添加到需要的位置(即,我们实际定义 Event1、Event2...的位置)?
类似的东西
enum class EventId { //add element Eventtype1 };
class Event1 : public Event
{
public:
Event1( Info* i )
:
i(i)
{}
EventId GetId() const override
{ return EventId::Eventtype1; }
public:
Info* i;
};
这样,并非每种类型的事件或使用所述事件的观察者类型都需要了解所有其他类型的事件,因为它们对它们来说毫无用处,并且实际上可以“扩展”事件我们无需编辑 Event 类本身即可拥有的事件类型。
经过一段时间的思考,我需要做什么,我选择使用基于唯一整数的 ID,而不是枚举。 我在互联网上找到了一些东西并对其进行了修改以更好地满足我的需求:
#define ADD_UNIQUE_ID \
private: \
static void getUniqueIdPrivate() { std::string val(__FILE__); volatile int val2 = __LINE__; } \
public: \
virtual const size_t getUniqueId() const { return reinterpret_cast<size_t>(getUniqueIdPrivate); } \
static size_t getClassUniqueId() { return reinterpret_cast<size_t>(getUniqueIdPrivate); }
它的作用是为类创建一个静态函数,然后使用该函数的内存地址作为 ID。它提供了两种不同的方式来访问所述函数,一种是虚拟的,能够通过基类指针访问它,一种是静态的,能够在不需要创建实例的情况下访问它。
这并不像我想要的那么容易,但这是一个很好的技巧,特别是如果我们将它定义为一个宏,然后我们可以轻松地将其添加到我们的类中。