C++中靜態建構函式和靜態解構函式的類比
C++中沒有靜態建構函式和靜態解構函式,但我們又經常得對類的靜態成員變數進行初始化,而寫一個靜態函數,在主函數中去調用的做法又太不優雅了。所以我寫出了下面的實現來類比靜態建構函式和靜態解構函式。不過我必須先聲明的是,這個實現可能有很隱晦的bug,具體請見最後的說明,同時也希望大家給出意見和建議,先謝了。
template<class T>
class StaticCtorAndDtor
{
public:
StaticCtorAndDtor()
{
T::StaticConstruct();
}
~StaticCtorAndDtor()
{
T::StaticDestruct();
}
};
#define DECLARE_STATIC_CONSTRUCT_DESTRUCT( ClassName )/
private:/
friend class StaticCtorAndDtor< ClassName >;/
static StaticCtorAndDtor< ClassName > _m_s_ctor_dtor_;/
static void StaticConstruct();/
static void StaticDestruct();
#define IMPLEMENT_STATIC_CONSTRUCT_DESTRUCT( ClassName )/
StaticCtorAndDtor< ClassName > ClassName::_m_s_ctor_dtor_;
測試代碼如下:
class CStaticConstructDestruct
{
DECLARE_STATIC_CONSTRUCT_DESTRUCT( CStaticConstructDestruct )
public:
static int i;
static int j;
};
IMPLEMENT_STATIC_CONSTRUCT_DESTRUCT( CStaticConstructDestruct );
int CStaticConstructDestruct::j = 2345;
int CStaticConstructDestruct::i = 2345;
void CStaticConstructDestruct::StaticConstruct()
{
i = 1234;
j = 1234;
}
void CStaticConstructDestruct::StaticDestruct()
{
}
int __cdecl _tmain(int argc, _TCHAR** argv)
{
printf("i = %d, j = %d/n", CStaticConstructDestruct::i, CStaticConstructDestruct::j);
return 0;
}
前面提到的bug就是靜態成員變數的初始化順序問題,因為_m_s_ctor_dtor和i、j一樣,都是CStaticConstructDestruct的靜態成員變數,它們誰先初始化對結果有很大的影響。雖然測試過程中(vs2003,按不同的順序聲明它們,把它們的執行個體化放到不同的cpp中去)的程式輸出一直與我期望的一致,但我真的沒法保證這一點。不知哪位能查一下C++標準,看這樣做是否有理論依據。
2004.8.29
今天又測試了一下, bug出現了, 不過C++中規定同一編譯單元中的靜態變數將按照定義的先後順序構造,並按逆序析構,所以繞過這個bug的方法就是:總是把類的所有靜態變數放到同一個cpp中去定義,並且總是把IMPLEMENT_XXX_XXX_XXX放到該檔案的最後一行.另外,在繼承中,衍生類別靜態構造是否能訪問基類靜態成員還沒有測試,還有多重繼承、虛擬繼承,嗚... 快暈死了, 不過好在這些東西一般情況下沒人用