我想初始化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设计模式的文章。