看了不少C++書,當講到靜態變量的時候,總是以int成員來舉例,是啊,這樣很好理解。但是如果這個靜態變量是一個對象行不行呢?不僅行,有時候還非常必要,而且別有洞天。
比如:
// .h 文件 class SystemGlobal { public: static ConfigXML* m_pInstance; } // .cpp 文件 ConfigXML* SystemGlobal::m_pInstance = new ConfigXML(); SystemGlobal::SystemGlobal(void) { }
那么應該何時刪除這個對象呢?想了很久,一開始覺得應該是在main()函數里,我這是還是QT程序,不得不改寫了main()函數通常的return 方式,變成這樣:
MainWidget main_widget; main_widget.showWidget(); int ret = app.exec(); delete SystemGlobal::m_pInstance; return ret;
我試了試,程序可以正常退出。反正我試了5遍都沒有問題。普通C++程序沒有app.exec的困擾,應該更加沒有問題。
---------------------------------------------------------
然后我又在網上搜了搜(很難搜到啊),受這個帖子啟發:
http://bbs.csdn.net/topics/200006181
改成在擁有靜態變量對象的類析構函數里刪除它,如下:
SystemGlobal::~SystemGlobal(void) { delete SystemGlobal::m_pInstance; }
同樣試了5次,也沒有問題。
但是我覺得這種方法不好,因為萬一SystemGlobal在整個項目中有多個實例呢,難道銷毀一個實例的時候,就必須銷毀這個靜態對象?這種方法只適合於整個項目就這一個SystemGlobal實例的情況。而且析構函數不允許重載和參數,就顯得更加有問題了。
---------------------------------------------------------
最后要提一句,靜態變量對象的初始化不僅僅別有洞天,而且實際上是相當重要的,因為它會在main()函數開始前執行,這代表什么?代表在main()函數的第一句語句執行之前,已經執行過這個靜態變量對應的類的構造函數了,而構造函數本身可以執行無窮無盡的語句,相當於main()函數只是一個正房,在正房出現前,程序員已經與小三天翻地覆一番后才回來了(真是經典案例!),而且這個小三仍存在於內存之中,與正房並列。
不要奇怪,其實MFC的執行流程就是從CMyApp(繼承於CWinApp)的theApp實例生成的過程開始的(注意,theApp不是靜態變量對象,但卻是一個寫在.cpp文件中的全局對象,其實與靜態變量對象也沒有什么本質的區別,也正因為theApp對象的指針仍需要被獲取,但又沒有靜態變量那么方便,所以微軟專門提供了AfxGetApp()全局函數。但是為什么提供這個函數,而不是使用靜態變量對象呢?我覺得2個原因,1是靜態變量名稱又臭又長,2是函數具有更好的封裝性,可以做更多的檢查乃至偷天換日):
MyApp::MyApp() { // 斷點2,在括號這行下斷點 } MyApp theApp; // 斷點1,在這行也下斷點 BOOL MyApp::InitInstance() { } // 斷點3,手動打開appmodul.cpp文件,然后在_tWinMain的括號處下斷點 extern "C" int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,__in LPTSTR lpCmdLine, int nCmdShow) { return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow); }
執行,通過追蹤MFC源代碼,可以發現程序首先定位於斷點1,按F11追蹤,發現會落在斷點2。繼續按F11,會發現執行CWinApp::CWinApp(LPCTSTR lpszAppName),然后按F10,發現會執行一大堆語句才會返回。可見的確實別有洞天。做完這些事情以后,就開始執行WinMain函數了(斷點3),具體可以發現WinMain函數是在appmodul.cpp文件中。
讀書筆記,兩種效果:1. 在MFC初始化完成后,WinMain被自動調用,兩者就相互聯系起來了 2. MFC沒有也不可能封裝WinMain函數(有待進一步闡述)
參考:
http://www.cnblogs.com/zhili/p/mfcanalyze.html
http://www.moon-soft.com/program/bbs/readelite9623.htm
http://www.cnblogs.com/suncoolcat/p/3367627.html
http://www.xuebuyuan.com/2119787.html (彩色貼圖,比較清楚)
http://cnmqw.iteye.com/blog/1921782 (精簡了代碼,非常清楚)
