通过接口复制事件对象

Copy event objects through the interface

我目前正在做一个小项目并添加一个事件系统。我正在尝试推迟事件,以便可以在更新阶段的事件部分处理它们。但问题是我不知道如何从 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 不变,但我不确定如何复制引用。

提前致谢。

问题是一个基 class 不知道如何动态复制其 children 的构造实例。相反,Event 接口将需要为 child classes 公开一种通用方法来定义如何复制自身,这种操作通常称为“克隆”。

您可以使用以下方法:

class Event {
...

public:
    virtual Event * clone() = 0;

...
}

每个 child class 必须使用它们的复制构造函数实现 clone 到 return 当前实例的副本:

class ChildEvent {
public:
    virtual ChildEvent * clone() {
        return new ChildEvent(*this);
    }

...
}

然后您的用例将如下所示:

Event* event = e.clone();

(顺便说一句,在这些情况下使用 ::std::unique<>() 通常比 return 使用原始指针更好,但我会把它留给你)

我不认为多态复制事件对象是您真正需要的(尽管这会起作用),而是 将这些事件对象的所有权 转移到和从事件队列。

很可能,事件在某处生成,然后存储在事件队列中。最终,存储在队列中的事件被提取并传递给其他组件,这些组件将处理它们或进一步转发它们以供使用。

我想说的是,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));
}

此函数的 调用者 最初拥有 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 将事件的所有权从队列转移到函数本身。最后,通过按值返回 std::unique_ptr<Event>,所有权进一步转移给 调用者 PopEvent()