我想初始化2个注册一些值(A,B)的类(例如Class ARegister,Class BRegister)。我想从super(?)类(例如Class RegisterALL)初始化这两个类。

例如:RegisterALL类将初始化ARegister和BRegister。因此,使用该模块的任何人都不必分别创建ARegister和BRegister的对象,而是可以创建RegisterALL的对象。

我想在构造函数中进行所有这些注册。因此,所有要做的就是创建RegisterALL类的对象,并且注册会自动发生。

我们不在项目中使用异常。因此,如果注册中存在某些错误,则无法知道。

我应该使用单独的成员函数来进行注册还是让构造函数进行注册。

我是面向对象设计的新手。我认为设计有问题,如果您指出正确的方法,将会很有帮助。

最佳答案

最好的方法是使用CRTP(奇怪的循环模板模式),派生类ARegister和BRegister将自己作为模板参数传递给基类RegisterALL。
它看起来像这样:

class RegisterAll
{
public:
    template<class DerivedType>
    DerivedType *createType()
    {
        RegisterAll *r = (*(m_creators[DerivedType::id]))();
        return dynamic_cast<DerivedType *>(r); //static_cast will work too if you didn't make a mistake
    }
protected:
    static std::map<int,RegisterAll *(*)()> m_creators;
};

std::map<int,RegisterAll *(*)()> RegisterAll::m_creators = std::map<int,RegisterAll *(*)()>();

template<class Derived>
class CRTPRegisterAll : public RegisterAll
{
public:
    static bool register()
    {
        RegisterAll::m_creators.push_back(std::make_pair(Derived::id,Derived::create);
        return true;
    }

private:
    static bool m_temp;
};

template<class Derived>
bool CRTPRegisterAll<Derived>::m_temp = CRTPRegisterAll<Derived>::register();

class RegisterA : public CRTPRegisterAll<RegisterA>
{
private:
    static RegisterA *create()
    {
        //do all initialization stuff here
        return new RegisterA;
    }

public:
    static const int id = 0;
};


现在,m_temp中静态变量CRTPRegisterAll的初始化将每个派生类型的创建者函数推入RegisterAll的列表。让RegisterAll知道所有派生类通常不是一个很好的设计(它不是很可扩展的)。这样,可以在每个派生类中实现实际的创建方法,并且创建者功能将自动注册到RegisterAll中。 CRTP的主要优点之一是,派生类不需要知道如何将自己注册到基类的列表,而是为他们完成的。至于错误处理,也可以在每个派生类的创建者函数中实现。有更好的方法来处理id问题,但我不想在这里讨论。
如果您想使用更简单的方法,建议阅读有关Factory设计模式的文章。

09-06 13:35