【发布时间】:2018-02-03 20:49:42
【问题描述】:
我正在创建一个简单的事件系统,其中可以通知多个侦听器关于特定主题的通知,并且当触发事件时,它可以将通用有效负载传递给事件,并且侦听器将匹配触发事件的格式。但是,由于无法在虚函数上使用模板,我还能如何实现呢?
class AEventListener
{
public:
template<class T>
struct PayloadObject {
T obj;
};
explicit AEventListener();
virtual ~AEventListener();
//error here because T is undefined. Each PayloadObject may have a different type
virtual void notify(vector<shared_ptr<PayloadObject<T>>> payload) = 0;
};
当事件主题订阅了侦听器时会调用 notify 方法,但我想要一种通用方法,将大量随机对象传递给侦听器。
例如
fireEvent("test.topic", Payload { 0, "hello", 123 });
//...
listener.notify(payload);
我将如何在 C++ 中解决这个问题?
我已经设法解决了这个问题,尽管我认为这不是最好的方法并且可能会降低性能。
template<class T>
struct PayloadObject : public APayloadObject {
T obj;
PayloadObject(T obj) {
this->obj = obj;
}
~PayloadObject() override {
};
};
struct APayloadObject {
virtual ~APayloadObject();
};
开火:
vector<shared_ptr<APayloadObject>> payload;
payload.push_back(shared_ptr<PayloadObject<int>>(new PayloadObject<int>(5))); //payload[0] = int - 5
Events::fire(EventKeys::DISCONNECTION_EVENT, payload);
通知:
shared_ptr<PayloadObject<int>> number = dynamic_pointer_cast<PayloadObject<int>>(payload[0]);
int id = number.get()->obj; //payload[0] = int - 5
【问题讨论】:
-
虚函数的重点是动态调度。模板的重点是静态调度。您不能在动态调度的函数中拥有静态确定的类型。那样不行。
-
一个注意事项 - 使用
make_shared而不是在shared_ptr构造函数中使用 new -
@bartop 感谢您的反馈 - 这是有原因的吗?
-
@jjmcc 最重要的是 -
make_shared分配一个堆,而new版本分配两个 - 第一个用于对象,第二个用于控制块。在这样的上下文中使用new也会导致意外的内存泄漏。这篇文章:stackoverflow.com/questions/18301511/… 给出了非常明确的答案