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