从基类构造函数调用派生类的方法

时间:2013-06-17 16:53:46

标签: c++ c++11

我有一种情况,我希望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派生的每个类都订阅该事件的最佳方法是什么,并且他们都必须为事件处理程序定义自己的实现?或者强迫这种行为太不方便,以便以其他方式实现?

1 个答案:

答案 0 :(得分:2)

OP在评论中说(empahsis 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()。这仍然是两阶段初始化,但它在函数调用后隐藏了。