C ++:如何在启动时创建类的集合

时间:2014-03-10 01:30:17

标签: c++ class lambda initialization class-factory

我正在使用C ++ 11.我有N个源文件,每个文件都包含一个继承自公共基类的类。在启动时,我希望每个类都将自己注册到一个集合中。注册包括1)识别类目的所必需的数据,2)用于创建类实例的类工厂。源文件的数量未知。这样做的模式是什么?该解决方案需要与Visual Studio 2013,gcc和其他人跨平台兼容。

3 个答案:

答案 0 :(得分:1)

首先要做的事情:请记住,只有在从单个Base类派生类时才能实现这一点,因为每个vector实例只能存储一种类型的对象。 / p>

当谈到解决方案时...你可以在相应的* .cpp文件中声明一个对象(在* .h文件中将其标记为extern):

// SomeClass.h
// <-- class declaration goes here
extern SomeClass someObj;

// SomeClass.cpp
SomeClass someObj;

并将其添加到构造函数中的向量:

SomeClass(){
   myVector.push_back(*this);
}

请注意,myVector需要在此范围内可见。

在您将myVector文件包含在SomeClass.h的一个实例后,应填充SomeClass。请注意,如果在基类中完成填充,则不必在每个后续子类中执行此操作,因为无论如何都会调用基本构造函数。

答案 1 :(得分:0)

听起来像Observer Pattern。根据您对此类列表的要求,可能会有更好的模式。

交叉兼容性完全取决于您的实施,但不应该存在问题。

答案 2 :(得分:0)

使用@ Pawel的建议,我创造了一个例子。目标是创建一个收集类列表的注册过程,每个注册都有一个类工厂和任意数据。具体来说,此示例将Mime类注册到std :: map中。注册条目包含内容类型字符串的向量,以及用于创建Mime类的类工厂。

在每个源文件中,我使用一个衬垫来注册该类。传递内容类型向量以指定类的支持类型。每个类都继承自名为Mime的基类(未显示)。

RegisterTypes<Swagger> swagger(vector<const char *>({ "application/swagger+json" }));

在头文件中,定义包含注册条目的结构。需要两个初始值设定项,内容类型向量和类工厂(实现为lamda)。

struct Registry
{
public:
    Registry() {} // initializer below forces this initializer to be needed
    Registry(vector<const char *> ct, function<Mime*(void)> cf) : contentTypes(ct), classFactory(cf) {}
    vector<const char *> contentTypes;
    function<Mime*(void)> classFactory;
};

在头文件中,extern一个std :: map,它将包含注册。每个映射条目都包含一个键和一个注册结构。实际定义在.cpp文件中(未显示)。注册表使用结构,因此它可以包含多个值。

extern std::map<const string, struct Registry> Mimes;

在头文件中,定义注册类。注册类的每个实例化都将在std :: map中创建注册条目。在此示例中,注册类创建一个注册条目,该条目由键(类名),支持的内容类型向量和类工厂组成。类工厂创建类的实例,并实现为lamda。每个注册的类都有一个共同的基类Mime。

template<class T> class RegisterTypes
{
public:
    RegisterTypes(vector<const char *> contentTypes)
    {
        Mimes[typeid(T).name()] = { contentTypes, [](void) -> Mime * { return (Mime *)(new T()); } }; // requires a matching explicit initializer
    }
};