C++:编译未使用的类

C++: Compiling unused classes

本文关键字:未使用 编译 C++      更新时间:2023-10-16

我喜欢使用以下模式来实现工厂类(取自我对这个问题的回答):

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的成员temp注册创建者函数。这可能有点复杂,但很容易使用。问题是AFactory没有编译,所以它的静态参数在加载时没有初始化。我的问题是,是否可以强制编译器(我使用的是VS 2012,但GCC的答案也很好)编译AFactory,而不显式地创建它的实例?我在VS中使用的一个解决方案是dllexport AFactory,这样编译器编译类,即使它不知道有人在实例化它。这是因为它假设其他dll可能会实例化它。这个解决方案的问题是,工厂类必须在一个单独的dll中实现,作为其余代码。而且这对GCC也不起作用。

CRTPFactory<AFactory,A>继承会导致类的隐式实例化,但不会导致其成员的定义。

[temp.inst]

类模板专门化的隐式实例化导致类成员函数、成员类、静态数据成员和成员模板的声明的隐式例示,而不是定义或默认参数的隐式例证;

您可以简单地显式实例化m_temp成员,而不是从CRTPFactory<AFactory,A>继承。

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

你的假设是错误的。CCD_ 5是绝对编译的。可能有好几次,因为它在一个标题中。

您真正的问题可能是class AFactory没有注册。为什么会这样?哪种说法会导致它?每个语句最终要么从main()调用,要么从全局变量的初始值设定项调用。