静态初始化

f4.*_*f4. 6 c++

上下文

我正在开发一个有一些"模块"的项目.我在这里称之为模块的是一个简单的类,它实现了一个特定的功能,并从一个强制接口的抽象类GenericModule派生.

应该在将来添加新模块.

可以同时加载模块的多个实例,也可以不加载,具体取决于配置文件.

我认为,如果未来的开发人员能够在一个简单的行中"注册"他的模块系统就会很棒.或多或少与他们在谷歌测试中注册测试的方式相同.

上下文²(技术)

我正在使用visual studio 2005构建项目.代码完全在库中,除了exec项目中的main().我想保持这种方式.

我的解决方案

我在谷歌测试中找到了灵感.

我创建了一个模板化的工厂.看起来或多或少像这样(我跳过了不感兴趣的部分,以保持这个问题有点可读):

class CModuleFactory : boost::noncopyable
{
public:
    virtual ~CModuleFactory() {};

    virtual CModuleGenerique* operator()(
        const boost::property_tree::ptree& rParametres ) const = 0;
};

template <class T>
class CModuleFactoryImpl : public CModuleFactory
{
public:
    CModuleGenerique* operator()(
        const boost::property_tree::ptree& rParametres ) const
    {
        return new T( rParametres );
    }
};
Run Code Online (Sandbox Code Playgroud)

和一个应该注册模块并将其工厂添加到列表的方法.

class CGenericModule
{
    // ...
    template <class T>
    static int declareModule( const std::string& rstrModuleName )
    {
        // creation de la factory
        CModuleFactoryImpl<T>* pFactory = new CModuleFactoryImpl<T>();

        // adds the factory to a map of "id" => factory
        CAcquisition::s_mapModuleFactory()[rstrModuleName ] = pFactory;

        return 0;
    }
};
Run Code Online (Sandbox Code Playgroud)

现在在模块中,我需要做的就是声明一个模块:

static int initModule =
acquisition::CGenericModule::declareModule<acquisition::modules::CMyMod>(
    "mod_name"
    );
Run Code Online (Sandbox Code Playgroud)

(将来它将被包装在允许的宏中

DECLARE_MODULE( "mod_name", acquisition::modules::CMyMod );
Run Code Online (Sandbox Code Playgroud)

)

问题

好吧,现在问题.

问题是,它确实有效,但不完全是我想要的方式.

如果我将initModule的定义放在模块的.cpp(我希望拥有它)中(甚至在.h中),则不会调用declareModule方法.如果我将静态init放在一个用过的.cpp文件中..它可以工作.

使用我的意思是:在其他地方调用代码.

视觉工作室似乎在构建库时丢弃了整个obj.我猜那是因为它没有在任何地方使用.

我激活了详细的链接,并在传递n°2中列出了库中的.objs,并且模块的.obj不存在.

几乎解决了?

我找到了这个并尝试添加/OPT:NOREF选项,但它没有用.我没有尝试在函数的.h中放置一个函数并从其他地方调用它,因为整个点就是能够在它的文件中的一行中声明它.

另外我认为问题与类似,但解决方案是针对g ++而不是视觉:'(

编辑:我刚刚阅读了这个问题的答案中的注释.好吧,如果我#include来自另一个.cpp的模块的.h,并将init放在模块的.h中.它工作,初始化实际上完成两次...每个编译单元一次?好吧它似乎发生在模块的编译单元......

旁注

如果你不同意我正在尝试做的事情,请随意告诉,但我仍然对解决方案感兴趣

Gre*_*jan 1

我根据 wxWidgets 的代码得到了类似的东西,但是我只将它用作 DLL。然而,wxWidgets 代码可以与静态库一起使用。

可能有所不同的一点是,在 wx 中,以下内容的等价物是在类范围内定义的。

static int initModule =
acquisition::CGenericModule::declareModule<acquisition::modules::CMyMod>(
    "mod_name"
    );
Run Code Online (Sandbox Code Playgroud)

类似于下面的内容,Factory因为它是静态的,所以它的创建会导致它被加载到工厂列表中。

#define DECLARE_CLASS(name)\
class name: public Interface { \
    private: \
        static Factory m_reg;\
        static std::auto_ptr<Interface > clone();

#define IMPLEMENT_IAUTH(name,method)\
    Factory name::m_reg(method,name::clone);\
Run Code Online (Sandbox Code Playgroud)