在C#中,類的靜態建構函式用於在使用類之前進行相關的初始化工作;比如,初始化靜態成員或執行特定操作。CLR 在第一次建立該類對象或調用該類靜態方法時自動調用靜態建構函式。同時,CLR保證靜態建構函式的執行緒安全性(準確地說是,只會調用一次,不存在多線程問題)。
下面是MSDN對靜態建構函式特點的描述:
1.靜態建構函式既沒有存取修飾詞,也沒有參數
2.在建立第一個執行個體或引用任何靜態成員之前,將自動調用靜態建構函式來初始化類
3.無法直接調用靜態建構函式
4.在程式中,使用者無法控制何時執行靜態建構函式
C++語言規範並未包含類似靜態建構函式的東西,但在使用類之前做初始化工作的需求卻是客觀存在的。就滿足需求本身來講,C++完全可以通過手動方式實現,但要處理好初始化時機,執行緒安全性等問題。本文則嘗試通過C++的模版機制類比實現靜態建構函式,避免手動初始化的繁瑣實現。對於需要靜態建構函式的類A,只需用繼承static_constructable模版類,並提供 static void statici_constructor()靜態方法即可:
輸出:
下面是static_constructable類模板的實現:
上面的實現把對A::static_constructor()的回調放到內部類helper的建構函式中;並在static_constructable()中定義一個helper局部靜態變數;C++保證在構造衍生類別 A的對象時,會先調用基類static_constructable的建構函式,且靜態局部變數只會構造一次,這樣就達到調用一次且僅一次A::static_constructor()的目的。
static_constructor類模板簡單地類比了C#的靜態建構函式機制,它具有以下特點:
1. 在第一次構造類對象之前自動調用類提供的靜態建構函式
2. 靜態建構函式被調用的時機是確定的
3. 利用了C++的局部靜態變數初始化機制保證了執行緒安全性(更正:實際並非安全執行緒,C++標準不涉及多線程問題,而一般編譯器實現也非安全執行緒,更多參見評論部分)
4. 基於繼承的實現機制並未改變衍生類別的對象記憶體布局
不過,和本文開始列出的C#靜態建構函式的幾個特點相比,本實現還有明顯的不足:無法通過調用類A的靜態方法觸發靜態建構函式;類A的靜態建構函式必須是public的。