这个问题与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

现在在这种情况下,在注册之间没有明确的顺序 ab 课程,但这可能不是问题。另一方面,通过使用 本地静态变量 在里面 registry::instance 函数保证可以执行单例的初始化 任何电话 registry::register 方法(作为第一次呼叫的一部分 instance 方法)。

如果您无法做出改变,那么您基本上是不运气的,您不能保证 registry 将在其他翻译单元中的其他静态成员属性(或全球)之前实例化。如果是这种情况,那么您将必须将课程注册到第一个实例化,并将代码添加到要注册的每个类的构造函数中,以确保课程已注册 物体的实际结构。

这可能是解决方案,具体取决于其他代码是否创建类型的对象。在工厂功能的特定情况下(第一个想到的),如果没有其他东西可以创建类型的对象 a 或者 b...然后,在构造呼叫上的支撑登记也不是解决方案。

其他提示

它是反对OOP范式的,但是让您的静态成员形成一个由2个全球变量引导的链接列表呢?您可以做这样的事情:

ClassRegistrator *head=NULL;
ClassRegistrator *tail=NULL;

struct ClassRegistrator {
    ... //data that you need
    ClassRegistrator *next;
    ClassRegistrator(classData ...) {
      if (head==NULL) head=tail=this;
      else {
        tail->next=this;
        tail=this;
      }
      ... //do other stuff that you need for registration
    }
};


class MyClass { //the class you want to register
    static ClassRegistrator registrator;
}

ClassRegistrator MyClass::registrator(...); //call the constructor

相信 全球变量,因为它们不需要 构造函数, ,但仅仅是纯数据,可以保证在您开始执行代码时已经初始化。

显然,这不是线程安全等,而应该使您的工作完成。

这是候选人 Singleton图案. 。基本上,您希望在实例化子类实例时实例化容器。可以通过检查Singleton指针在基类构造函数中是否为空,如果是的,则可以实例化。

一个想法是通过 登记 函数的函数。每个后代将执行要注册的功能。该函子可以通过构造函数传递。

例子:

struct Registration_Interface
{
  virtual void operator() (const std::string& component_name) = 0;
};

struct Base
{
};

struct Child1
  : public Base
{
  Child(Registration_Interface& registration_ftor)
  {
     //...
     registration_ftor("Child1");
  }
};

看: http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.14

一种选择是在添加第一件事时懒惰地构建容器:

  void AddToContainer(...) {
    // Will be initialized the first time this function is called.
    static Container* c = new Container();
    c->Add(...);
  }

“模仿”静态构造函数的唯一方法是明确调用功能以执行静态初始化。没有其他方法仅通过在模块中链接来运行代码预先处理。

您可以使用“初始使用”模式,然后实例化虚拟静态实例,以尽早确保初始化。

class cExample
{
    public :
       cExample() ;

       // Static functions here

    private :
        static bool static_init ;

        // other static members here
}

cExample::static init = false ;

cExample::cExample()
{
    // Static initialisation on first use
    if( !static_init )
    {
        // initialise static members
    }

    // Instance initialisation here (if needed)
}

// Dummy instance to force initialisation before main() (if necessary)
static cExample force_init ;
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top