问题描述
我正在尝试重写一些旧代码以使其更加面向对象。以前我有一个 struct 的 union ,叫做Event
union Event {
AEvent aEvent;
BEvent bEvent;
CEvent cEvent;
}
,此Event
稍后将在结构中使用
struct EventImpl {
... //some other members
Event event();
}
现在我正在尝试使用功能强大的shared_ptr
;
我创建了一个名为BaseEvent
class BaseEvent{
size_t m_TypeHash;
public:
using Ptr = std::shared_ptr<BaseEvent>;
virtual ~EventDesc() = default;
template <class T>
// cast to different events
static std::shared_ptr<T> Cast(const Ptr& src) {
return src->m_TypeHash == typeid(T).hash_code()
? std::static_pointer_cast<T>(src)
: nullptr;
}
protected:
BaseEvent(size_t typeHash) : m_TypeHash(typeHash){}
};
从这里开始,AEvent
,BEvent
和CEvent
可以仅扩展BaseEvent
,从而使代码更简洁。
但是问题来了,如何处理包含EventImpl
的结构Event
?有没有办法初始化通用的BaseEvent
?
struct EventImpl {
... //some other members
BaseEvent<T> event; //??
T event; // ??
std::shared_ptr<BaseEvent> event; // ???
}
修改:
正如德米特里(Dmitry)指出的那样,EventImpl
这个名称有点误导,EventWrapper
认为更合适。 :)
解决方法
有很多不同的方法可以做到这一点。首先,您可以使用std::variant
作为union
的OOP感知替代品:
using Event = std::variant<AEvent,BEvent,CEvent>;
另一种方法是使用动态多态性:您需要为所有XEvent
类型定义一个基类:
class BaseEvent {};
class AEvent : public BaseEvent {};
动态多态性的另一个方面是如何返回值:通过原始指针,通过引用,智能指针等。std::shared_ptr
可能是过大的,std::unique_ptr
应该是第一个成语考虑。
struct EventWrapper {
std::unique_ptr<Event> event();
};
我有意将EventImpl
重命名为EventWrapper
,因为如果您使用Impl
惯用语,则应使用相反的关系:
struct EventImpl;
class Event {
std::unique_ptr<EventImpl> _impl;
};
class AEventImpl : public EventImpl {};
class BEventImpl : public EventImpl {};
class CEventImpl : public EventImpl {};