【发布时间】:2010-06-23 19:37:13
【问题描述】:
上下文
我正在做一个有一些“模块”的项目。 我在这里所说的模块是一个简单的类,它实现了一个特定的功能,并从一个抽象类 GenericModule 派生出来,它强制一个接口。
未来应该会添加新模块。
一个模块的多个实例可以同时加载,也可以不加载,具体取决于配置文件。
我认为,如果未来的开发人员可以通过简单的一行将他的模块“注册”到系统中,那就太好了。他们在谷歌测试中注册测试的方式或多或少相同。
上下文²(技术)
我正在使用 Visual Studio 2005 构建项目。 代码完全在一个库中,除了 main() 是在一个 exec 项目中。 我想保持这种状态。
我的解决方案
我从他们对谷歌测试所做的事情中找到了灵感。
我创建了一个模板化工厂。看起来或多或少像这样(我跳过了无趣的部分以保持这个问题的可读性):
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 );
}
};
还有一个方法应该注册模块并将它的工厂添加到列表中。
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;
}
};
现在在一个模块中,我需要做的就是声明一个模块:
static int initModule =
acquisition::CGenericModule::declareModule<acquisition::modules::CMyMod>(
"mod_name"
);
( 将来它会被封装在一个允许做的宏中
DECLARE_MODULE( "mod_name", acquisition::modules::CMyMod );
)
问题
好了,问题来了。
问题是,它确实有效,但不完全是我想要的方式。
如果我将 initModule 的定义放在模块的 .cpp 中(我想要它的位置)(甚至在 .h 中),则不会调用方法 declareModule。 如果我将静态初始化放在使用过的 .cpp 文件中......它可以工作。
我的意思是:在其他地方调用代码。
问题是视觉工作室在构建库时似乎丢弃了整个 obj。我猜那是因为它没有在任何地方使用。
我激活了详细链接,并在第 n°2 通道中列出了库中的 .objs 并且模块的 .obj 不存在。
几乎解决了?
我找到了this 并尝试添加/OPT:NOREF 选项,但没有成功。
我没有尝试将函数放在模块的 .h 中并从其他地方调用它,因为重点在于能够在其文件的一行中声明它。
我也认为这个问题类似于this one,但解决方案是g++不是视觉的:'(
编辑:我刚刚阅读了这个问题的答案中的注释。好吧,如果我#include来自另一个.cpp的模块的.h,并将init放入模块的.h中。它有效并且初始化实际上进行了两次......在每个编译单元中一次?好吧,它似乎发生在模块的编译单元中......
旁注
如果您不同意我的尝试,请尽管说出来,但我仍然对解决方案感兴趣
【问题讨论】:
-
如果模块不被使用,你为什么要关心它的注册?
-
'代码完全在库中'是静态的还是动态的?
-
@Georg 不是直接使用,而是通过 CModuleFactory 的接口使用。 @Greg 静态
-
@Georg Fritzsche;您可能不直接使用该模块,除了通过工厂注册您现在可以创建对象,然后通过抽象 API 使用它。
-
“我在这里所说的模块是一个简单的类”。那么,请称其为“班级”。如果是一堂课,请这样称呼它。请不要用似乎与实际问题无关的术语来混淆已经令人困惑的问题。
标签: c++