[英]C++: Compiling unused classes
我喜欢使用一种模式来实现工厂类,该模式如下所示(摘自对此问题的回答):
class Factory
{
public:
template<class DerivedType>
DerivedType::CreatedType *createType()
{
DerivedType::CreatedType *r = (DerivedType::CreatedType) (*(m_creators[DerivedType::id]))();
return r;
}
protected:
static std::map<int,void *(*)()> m_creators;
};
std::map<int,void *(*)()> Factory::m_creators = std::map<int,void*(*)()>();
template<class Derived, class CreatedType>
class CRTPFactory : public Factory
{
typedef typename CreatedType CreatedType;
public:
static bool register()
{
Factory::m_creators.push_back(std::make_pair(Derived::id,Derived::create);
return true;
}
private:
static bool m_temp;
};
template<class Derived>
bool CRTPFactory<Derived>::m_temp = CRTPFactory<Derived>::register();
class AFactory : public CRTPFactory<AFactory,A>
{
private:
static A *create()
{
//do all initialization stuff here
return new A;
}
public:
static const int id = 0;
};
这允许将工厂扩展为新类型,而不必更改工厂类别。 它还允许为不同类型实现特定的创建算法,而不必更改工厂类。 但是,这种模式存在一个主要问题。 永远不会显式使用AFactory类。 它在加载时通过CRTPFactory的成员临时寄存器注册其创建者函数。 这可能有点难以理解,但是非常易于使用。 问题在于AFactory未编译,因此其静态参数未在加载时初始化。 我的问题是,是否可以强制编译器(我使用的是VS 2012,但对GCC的回答也不错)而无需显式创建其实例即可编译AFactory吗? 我在VS中使用的一种解决方案是dllexport AFactory,这样编译器即使不知道有人实例化该类也可以编译该类。 这是因为它假定其他一些dll可能将其实例化。 此解决方案的问题在于,工厂类必须作为其余的代码在单独的dll中实现。 而且这在GCC上不起作用。
从CRTPFactory<AFactory,A>
继承会导致类的隐式实例化,但不会导致其成员的定义。
[temp.inst]
类模板专业化的隐式实例化导致类成员函数,成员类,静态数据成员和成员模板的声明而不是定义或默认参数的隐式实例化;
不必从CRTPFactory<AFactory,A>
继承,而是可以显式实例化m_temp
成员。
template bool CRTPFactory<AFactory,A>::m_temp;
作为参考,这是修改后的示例(以编译的形式):
#include <map>
class Factory
{
public:
template<class DerivedType, class CreatedType>
CreatedType *createType()
{
CreatedType *r = (CreatedType) (*(m_creators[DerivedType::id]))();
return r;
}
protected:
static std::map<int,void *(*)()> m_creators;
};
std::map<int,void *(*)()> Factory::m_creators = std::map<int,void*(*)()>();
template<class Derived, class CreatedType>
class CRTPFactory : public Factory
{
public:
static bool register_()
{
Factory::m_creators.insert(std::make_pair(Derived::id,Derived::create));
return true;
}
static bool m_temp;
};
template<class Derived, class CreatedType>
bool CRTPFactory<Derived, CreatedType>::m_temp = CRTPFactory<Derived, CreatedType>::register_();
struct A
{
};
class AFactory
{
public:
static void *create()
{
//do all initialization stuff here
return new A;
}
public:
static const int id = 0;
};
template bool CRTPFactory<AFactory,A>::m_temp;
静态类成员应在某处显式创建。
在您选择的cpp文件中执行以下操作应该可以:
int AFactory::id = 0
你误会了你的假设。 class AFactory
肯定已编译。 因为它在标题中,所以可能有好几次了。
您真正的问题可能是未注册 class AFactory
。 为什么会这样呢? 会导致以下哪种说法? 最终,每个语句都可以从main()
或全局变量的初始化程序中调用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.