Chr*_*ris 5 c++ static-constructor static-initialization
这是一个与 C++ 中对象初始化相关的问题。
我有一组类(不是实例),它们继承自一个公共基类,我需要它们在程序启动时在容器(特别是地图)中注册有关它们自己的信息。
问题是我需要它是动态的。容器定义在一个独立的项目中,不同于类。我宁愿避免制作库的多个硬编码版本,每个使用它的程序中的每一组类都有一个。
我想过在每个子类中都有一个特殊类的静态实例,这将在其构造函数中进行注册。但是,我发现没有办法保证在构造这些对象之前构造容器。
我还应该注意,在创建这些子类的任何实例之前,容器中关于子类的信息应该可用。
有没有办法做到这一点,或者在一般情况下模仿 C++ 中的静态构造函数?
您同时描述了不同的问题。对于某种静态初始化的特定问题,一种简单的方法是创建一个将执行注册的假类。那么每个不同的类都可以有一个static const X成员,该成员必须在翻译单元中定义,并且定义将触发实例的实例化和类的注册。
这并没有解决初始化订单惨败这一难题。该语言不对不同翻译单元中对象的初始化顺序提供任何保证。也就是说,如果您使用此类类编译三个翻译单元,则无法保证假成员的相对执行顺序。这也适用于库:如果您要在其中注册类的容器是全局/静态成员属性,则不能保证该容器已被初始化。
如果您有权访问代码,static local variables则可以修改容器代码以使用 ,这将在确保初始化顺序方面向前迈出一步。作为可能的解决方案的草图:
// 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
Run Code Online (Sandbox Code Playgroud)
a现在,在这种情况下,和类的注册之间没有明确的顺序b,但这可能不是问题。另一方面,通过在函数中使用局部静态变量,可以保证在对方法的任何调用之前registry::instance执行单例的初始化(作为第一次调用方法的一部分)。registry::registerinstance
如果您无法进行更改,那么您基本上就不走运,并且无法保证将registry在其他翻译单元中的其他静态成员属性(或全局变量)之前实例化。如果是这种情况,那么您必须将类的注册推迟到第一次实例化,并向每个要注册的类的构造函数添加代码,以确保在实际构造对象之前注册该类。
这可能是也不是一个解决方案,具体取决于其他代码是否创建该类型的对象。在工厂函数的特殊情况下(我想到的第一个),如果没有其他方法允许创建类型a或b...的对象,那么构造函数调用上的捎带注册也不是解决方案。