自行注册课程的替代方案

时间:2017-03-14 12:24:41

标签: c++

我的项目以两种方式使用自注册类:一种是实现工厂模式,允许迭代这些类的映射,实现几乎完全类似于C++ how safe are self registering classes?中描述的实现;另一种是将巨大的switch语句分成对象的映射。在后一种情况下,我刚刚创建了一个基类和一组派生类,然后我在源文件中使用静态对象实例化每个派生类,而类的构造函数在地图中注册它们。

现在我正在尝试将我的应用程序的逻辑部分移动到静态库中,并在两个子项目中使用此库(我使用Qt,Qt Creator和gcc)。在这样做之后,除非我在某处对这些类进行了明确的实例化,否则上述类都不起作用。

所以,我正在寻找任何解决方法。实际上,另一个问题出现了:使用自注册技术在c ++中设计应用程序是否是一个非常糟糕的内容?

编辑:我被要求举个例子。这是简化的代码:

// Class for storing actions
class ActionBase;
class SomeObject;    
class ActionMap
{
    public:
    ActionMap();
    static void registerAction(int n, ActionBase* action) {}
    void performAction (SomeObject* object, int action) {
         m_actions[action]->perform(object);
    }

 private:
     std::map<int, ActionBase*> m_actions;
};

// Action class - action.h
#include "actionmap.h"
class SomeObject;
class ActionBase
{
public:
     ActionBase(int n, ActionBase* action) {ActionMap::registerAction(n, action); }
     virtual ~ActionBase() = 0;
     virtual void perform(SomeObject* object) = 0;
 };

 template<int N>
 class Action : public ActionBase
 {
 public:
    Action() : ActionBase(N, this) {}
 };

 template<>
 class Action<1> : public ActionBase
 {
 public:
     Action() : ActionBase(1, this) {}
     void perform(SomeObject* object)
     {
      // Do something
     }
 };

现在我可以在动作源文件中创建一些动作对象,如:

// action.cpp
// #include "action.h"
static Action<1> action1;

重组项目后,我必须在子项目中的某处显式创建action1变量才能使用它,例如在main.cpp中。

更新:似乎Angew帮助我部分解决了第二个问题。我已经删除了一个空闲的空函数并在action.cpp中定义它。在app中的某个地方调用它会强制操作对象的初始化。

1 个答案:

答案 0 :(得分:2)

  

使用自注册技术在c ++中设计应用程序是一个非常糟糕的内容吗?

恐怕我得回答&#34;是的&#34;对这一个。 C ++明确允许在main启动后初始化非局部变量;唯一的限制是必须在执行定义它们的文件中的任何代码之前初始化它们。引用C ++ 14(N4140)[basic.start.init] 3.6.3 / 4:

  

实现定义是否使用静态存储动态初始化非局部变量   持续时间在main的第一个语句之前完成。如果初始化延迟到某个时间点   在main的第一个陈述之后,它应该在任何函数或变量的第一次使用(3.2)之前发生   在与要初始化的变量相同的翻译单元中定义。

换句话说,在文件中定义的全局变量(其初始化进行了一些注册)可能不会被初始化(并因此被注册),直到调用该文件中的其他代码为止。