这个问题与C中对象的初始化有关
我有一组类(非实例),继承自公共基类,我需要它们在程序启动时在容器(特别是地图)中注册自己的信息.
问题是我需要它是动态的.容器是在一个独立的项目中定义的,与类不同.我宁愿避免制作库的多个硬编码版本,每个使用它的程序中的每个类都有一个版本.
我想过在每个子类中都有一个特殊类的静态实例,这会在其构造函数中进行注册.但是,我发现无法保证在构造这些对象之前已经构造了容器.
我还应该注意,在创建这些子类的任何实例之前,容器中有关子类的信息应该是可用的.
有没有办法做到这一点,或者模仿C中的静态构造函数?
最佳答案 您正在同时描述不同的问题.在具有某种静态初始化的特定问题上,一种简单的方法是创建一个将执行注册的假类.然后,每个不同的类可以具有静态const X成员,该成员必须在翻译单元中定义,并且该定义将触发实例的实例化和类的注册.
这并没有解决难题,即初始化命令惨败.该语言不对不同翻译单元中对象的初始化顺序提供任何保证.也就是说,如果您使用此类编译三个翻译单元,则无法保证伪成员的相对执行顺序.这也适用于库:如果此类容器是全局/静态成员属性,则无法保证您要在其中注册类的容器已初始化.
如果您可以访问代码,则可以修改容器代码以使用静态局部变量,这将是向前迈出的一步,以确保初始化顺序.作为可能解决方案的草图:
// registry lib
class registry { // basically a singleton
public:
static registry& instance() { // ensures initialization in the first call
static registry inst;
return inst;
}
// rest of the code
private:
registry(); // disable other code from constructing elements of this type
};
// register.h
struct register {
template <typename T>
register( std::string name ) {
registry::instance().register( name, T (*factory)() ); // or whatever you need to register
}
};
// a.h
class a {
public:
static a* factory();
private:
static const register r;
};
// a.cpp
const register a::r( "class a", a::factory );
// b.h/b.cpp similar to a.h/a.cpp
现在在这种情况下,a和b类的注册中没有明确的顺序,但这可能不是问题.另一方面,通过在registry :: instance函数中使用本地静态变量,可以保证在调用registry :: register方法之前执行单例的初始化(作为第一次调用实例方法的一部分) .
如果你不能进行这种改变,你基本上没有运气,你不能保证在其他翻译单元中的其他静态成员属性(或全局变量)之前实例化注册表.如果是这种情况,那么您将不得不将类的注册推迟到第一个实例化,并将代码添加到要注册的每个类的构造函数中,以确保在实际构造对象之前注册该类.
这可能是一种解决方案,取决于其他代码是否创建了该类型的对象.在工厂函数的特定情况下(首先想到的是),如果没有其他任何东西可以创建类型为a或b的对象…那么在构造函数调用上的背负注册也不是解决方案.