任何一們面向對象語言裡都會涉及構造函數這一概念,只是實現的方式各有差異。需要這main函數之前執行一段代碼是非常容易的事情,只需要聲明一對象的全局變量,在構造函數可以為所欲為干你想干的事情。然而,對於面向過程的語言比如C,需要實現全局的構造函數就比較奇葩。當然gcc會有很優雅的解決方式,VC則猥瑣點。
其實在main函數裡面調用一下就可以了,是的,這樣是可以,但是對於框架的實現來說,這卻是不太好的,客戶使用起來不自由。當然也可以說,我是屌絲,我可以裝逼點。
gcc實現
gcc 實現是非常簡單的事情。在全局構造函數前叫以下編譯器屬性即可:
attribute((constructor))
vc實現
vc的實現比較奇葩,VC本身沒有類似·attribute·這樣的屬性,你需要將全局函數編譯到某個特定的代碼段裡面。MSDN對於這部分有詳細的說明:CRT Initialization
簡單來說就是將你的全局構造函數的函數指針編譯到·.CRT$XCU·段裡面。如何編譯到·.CRT$XCU·段?VC有VC的語法。
// 聲明在段·\.CRT$XCU·裡面生成代碼
#pragma section("\.CRT$XCU",read)
// 聲明需要調用的函數
__declspec(allocate("\.CRT$XCU")) void (\_\_cdecl *a)(void) = func;
// 調用的函數實現
void func(void){}
以上實現可以用下面實現:
#ifdef _MSC_VER
#define __CCALL __cdecl
#define __func__ __FUNCTION__
#define snprintf _snprintf
#pragma warning(disable:4996) // this is very violent
#pragma section(".CRT$XCU",read)
#define __CONSTRCT(a, b) \
void __CCALL __##a##__##b##__ ## 520hjm(void); \
__declspec(allocate(".CRT$XCU")) \
void (__CCALL * __ctor__##a##__##b##__ ## 520hjm)(void) = \
__##a##__##b##__ ## 520hjm;
#else
#define __CCALL
#define __CONSTRCT(a, b) __attribute__((constructor))
仿照gtest的簡易單元測試ctest就是用的這方面的知識。
這裡顯示效果不是很好,個人網站那裡效果好點http://luoguochun.cn/2014/06/25/c-constructor/