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

Calling a method of a derived class from base class constructor

本文关键字:方法 派生 函数调用 基类      更新时间:2023-10-16

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

// 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派生的每个类都订阅事件的最佳方法是什么,并且它们都必须为事件处理程序定义自己的实现?或者仅仅是强迫这样的行为太不方便了,所以应该用其他方式来实现?

OP在评论中说(强调我的):

我想我想有所有类派生自System 订阅一个事件,和被迫实现自己的处理程序说的事件。

"从X派生的所有类"answers"被迫"在同一句话中要求使用纯虚成员函数。

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