我目前正在开发一个小项目并添加一个事件系统。我正在尝试推迟事件,以便可以在更新阶段的事件部分中处理它们。但问题是我不知道如何从
Event*
复制或创建 Event&
。
这是问题的简化版本:
#include <list>
#include "Event.h"
std::list<Event*> queue;
Event* buffer;
void PushEvent(Event& e) {
// Copy Event in to some ptr. (This is the code I don't know how to write)
// It doesn't work because Event is an abstract type
Event* event = new Event(e);
queue.push_back(event);
}
Event& PopEvent() {
buffer = queue[0];
queue.erase(0);
return *buffer;
}
bool IsEmpty() {
return queue.empty();
}
我真的很想保持 API 相同,但我不知道如何复制参考。
提前致谢。
问题在于基类不知道如何动态复制其子类的构造实例。相反,
Event
接口需要为子类公开一种通用方法来定义如何复制自身,这种操作通常称为“克隆”。
您可以使用以下方法:
class Event {
...
public:
virtual Event * clone() = 0;
...
}
每个子类必须实现
clone
以使用其复制构造函数返回当前实例的副本:
class ChildEvent {
public:
virtual ChildEvent * clone() {
return new ChildEvent(*this);
}
...
}
然后您的用例将如下所示:
Event* event = e.clone();
(顺便说一句,在这些情况下使用
::std::unique_ptr<>()
通常很好,而不仅仅是返回原始指针,但我将把它留给你)
我不认为多态复制事件对象是您实际需要的(尽管这会起作用),而是将这些事件对象的所有权转移到事件队列或从事件队列转移。
很可能,事件在某个地方生成,然后存储在事件队列中。最终,存储在队列中的事件被提取并传递给其他组件,这些组件将处理它们或将它们进一步转发以供使用。我想说,
Event
对象的传输以及它们的所有权如何通过移动它们而受到影响是您需要关注的。
Event *
切换到
std::unique_ptr<Event>
,以清楚地说明谁拥有事件对象:
std::list<std::unique_ptr<Event>> queue;
这清楚地表明 queue
拥有它所持有的
Event
对象。
PushingEvent()
将采用
std::unique_ptr<Event>
而不是
Event&
:
void PushEvent(std::unique_ptr<Event> event) {
queue.push_back(std::move(event));
}
此函数的 caller 最初拥有 Event
对象,但在调用它时必须将所有权转移给此函数。然后,
PushEvent()
又将
Event
的所有权转移到事件队列,进一步将
std::unique_ptr<Event>
移动到队列中。与
PopEvent()
类似 – 只是方向相反:
[[nodiscard]] std::unique_ptr<Event> PopEvent() {
auto event = std::move(queue.front());
queue.pop_front();
return event;
}
事件队列最初拥有要弹出的 Event
对象。它通过局部变量
event
将事件的所有权从队列转移到函数本身。最后,通过按值返回
PopEvent()
,所有权进一步转移给调用者到
std::unique_ptr<Event>
。