C++ 自注册课程的替代方案

C++ 自注册课程的替代方案,c++,C++,我的项目以两种方式使用自注册类:一种是实现工厂模式,它允许迭代此类的映射,实现几乎完全类似于中描述的实现;另一种是将巨大的switch语句分离成对象映射。在后一种情况下,我刚刚创建了一个基类和一组派生类,然后在源文件中用静态对象实例化了每个派生类,而类的构造函数在映射中注册它们自己 现在我尝试将我的应用程序的逻辑部分移动到静态库中,并在两个子项目中使用该库(我使用Qt、Qt Creator和gcc)。这样做之后,除非我在某个地方对这些类进行了明确的实例化,否则上述类都不能工作 所以,我正在寻找解

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

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

所以,我正在寻找解决办法。实际上,另一个问题是:用C++自动注册技术来设计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
     }
 };
//用于存储操作的类
类操作库;
类对象;
类动作图
{
公众:
ActionMap();
静态无效注册表操作(intn,ActionBase*action){}
无效执行(SomeObject*对象,int操作){
m_actions[动作]->执行(对象);
}
私人:
映射m_动作;
};
//行动-集体行动
#包括“actionmap.h”
类对象;
类ActionBase
{
公众:
ActionBase(int n,ActionBase*action){ActionMap::registerAction(n,action);}
virtual~ActionBase()=0;
虚空执行(SomeObject*object)=0;
};
模板
集体诉讼:公共诉讼基础
{
公众:
Action():ActionBase(N,this){
};
模板
集体诉讼:公共诉讼基础
{
公众:
Action():ActionBase(1,this){}
执行void(SomeObject*对象)
{
//做点什么
}
};
现在我可以在actions源文件中创建一些action对象,例如:

// action.cpp
// #include "action.h"
static Action<1> action1;
//action.cpp
//#包括“action.h”
静态作用1;
重组项目后,我必须在子项目的某个地方显式地创建action1变量,以便能够使用它,例如在main.cpp中

更新:似乎Angew帮我部分解决了第二个问题。我已经清除了一个自由空函数,并在action.cpp中定义了它。在应用程序的某个地方调用它会强制初始化动作对象

用自注册技术设计C++应用程序是不是一个很不好的内涵? 恐怕我不得不对这个问题回答“是”。C++允许显式地允许非本地变量在 >主< /代码>开始后初始化;唯一的限制是,在执行定义它们的文件中的任何代码之前,必须对它们进行初始化。引用C++14(N4140)[basic.start.init]3.6.3/4:

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


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

“除非”您需要对此进行更多的解释,并尝试包含一个@RichardCritten,这很可能是链接器删除了包含注册实例的对象文件,因为没有人引用它。“如果你问我的话,那就是行为不检,但我们到了。”昆汀不一定。不要忘记,在C++中,文件范围变量只能在执行该文件的任何代码之前被初始化,但是在代码>主< /代码>开始后,它们可以被初始化。直到这实际上是明确的实现定义。。。对于静态注册对象来说,这是一个很糟糕的问题:/您的问题的解决方案如下所示: