[英]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.