2

我有一种情况,我希望每个派生实例都System通过我自己的事件系统订阅一个事件。基本上,这意味着将 std::function 传递给事件,该事件是另一个实例的成员字段。所以基本上是这样的:

// System.h
class System
{
    public:
        System(std::shared_ptr<EntityManager> entityManagerPtr);
        virtual ~System();
        virtual void componentAddedEventHandler(void* source, const ComponentAddedEventArgs& args);
    protected:
        std::shared_ptr<EntityManager> m_entityManagerPtr;
};

以及使用委托的实现:

// System.cpp
System::System(std::shared_ptr<EntityManager> entityManagerPtr) : m_entityManagerPtr(entityManagerPtr)
{
    // Subscribe to the componentAddedEvent
    m_entityManagerPtr->componentAddedEvent += [&](void* source, ComponentAddedEventArgs args) {
        this->componentAddedEventHandler(source, args);
    };
}

但显然,如果没有定义,这将无法编译System::componentAddedEventHandler()

确保每个派生类System都订阅事件的最佳方法是什么,并且它们都必须为事件处理程序定义自己的实现?还是强迫这种行为太不方便了,所以应该以其他方式实现?

4

1 回答 1

2

OP 在评论中说(emahsis mine):

我在想我想让所有派生的类System都订阅一个事件,并被迫为所述事件实现自己的处理程序。

“所有从 X 派生的类”和“被迫”在同一个句子中为纯虚成员函数尖叫。

struct System
{
     virtual void foo() = 0;
};

struct Subsystem : public System
{
     virtual void foo() override { /* forced to implement this */ }
};

如果您通过智能指针(也许在容器中)存储您的系统,您可以调用foo()每个系统并确保获得衍生类的行为。

这一切都很好,但你不能foo()从基类的构造函数中调用。这个问题的低技术解决方案是使用工厂函数来构造每个对象。

template <typename T>
unique_ptr<T> make_system()
{
    auto obj = make_unique<T>();
    obj->foo();
    return obj;
}

auto s1 = make_system<Subsystem1>();
auto s2 = make_system<Subsystem2>();

这两个对象都被强制实现,并且两个对象在使用之前foo()都已调用。foo()这仍然是两阶段初始化,但它隐藏在函数调用后面。

于 2013-06-17T19:11:39.783 回答