對于VS2003編譯器的BUG給予細致分析
最新的VS2003編譯器,是一個很通用的數據庫管理程序,到目前為止所有的代碼都是通過Visual Studio編寫,核心部分的設計基本完成,但愿可以通過.NET開發一些小的模塊,Visual Studio的程序員真的沒有多少精英啊。我們必須要用VS2003編譯器下的C++代碼升級到VS2005編譯器下,從而可以充分利用.NET與C++混合編程。
升級的基本過程如下:
1、首先備份現有的VC程序,備份之后啟動VS2005。
2、通過VS2005打開要升級的解決方案,系統提示自動轉換,如果VC程序已經被嵌入到VSS中,則系統將提示登錄VSS,并且自動將解決方案文件和項目文件簽出。(注意選擇備份原來版本 的解決方案的選項。)
3、一般情況下系統提示成功,可能會有兩個警告,可以不予理會。因為升級過程中僅僅修改了解決方案文件和工程項目文件,所以速度會很快,C++頭文件和CPP文件都不作任何修改(這和VB6到VB2005的升級不同),因此速度很快。#t#
4、在VS2005中重新編譯升級后的程序,很可能出現很多警告和錯誤提示,警告可以不予理會,錯誤提示必須修改。我所遇到的錯誤提示主要有兩種:一種提示是“某個變量沒有定義”,另外一種是模板類的消息映射的錯誤提示。
先說第一種錯誤提示,例如如下的兩個for循環語句
- for(int i=0;i<10;i++)
- {
- }
- for(i=0;i<100;i++)//
上面的語句在VS2003中沒有問題,在2005中則是錯誤的,2005將i作為第一個for循環中的局部變量處理,因此編譯器認為第二個for循環中的i沒有定義。這類錯誤可能有很多,但是修改起來比較容易。
第二種錯誤是模板類的消息映射宏錯誤。我在程序中設計了一個控件模板:
- #define UNI_FORMVIEW_CONTROLS(P) \
- typedef CUniDataCtrl<CEdit,P> MEDICONEXPORT CUniEdit; \
- typedef CUniDataCtrl<CEditAddress,P> MEDICONEXPORT CUniAddress; \
- typedef CUniDataCtrl<CComboBoxData,P> MEDICONEXPORT CUniComboBox; \
- UNI_FORMVIEW_CONTROLS(CMdcLayerPanel)
并通過typedef定義了很多VS2003編譯器類型(20多個)
- #define Map(T,B) \
- BEGIN_MESSAGE_MAP(T, B)\
- ON_WM_LBUTTONDOWN()\
- ON_WM_RBUTTONDOWN()\
- ON_WM_MOUSEMOVE()\
- ON_WM_SETCURSOR()\
- ON_WM_SETFOCUS()\
- ON_WM_KILLFOCUS()\
- ON_REGISTERED_MESSAGE(BCGM_PROPERTY_CHANGED,OnPropertyChange)\
- END_MESSAGE_MAP()
- #define MSG_MAP_UNI_EDIT Map(CUniEdit,CEdit)
- #define MSG_MAP_UNI_ADDRESS Map(CUniAddress,CEditAddress)
- #define MSG_MAP_UNI_COMBOBOX Map(CUniComboBox,CComboBoxData)
- #define MSG_MAP_UNI_DATETIMECTRL Map(CUniDateTimeCtrl,CMyDateTimeCtrl)
- #define MSG_MAP_UNI_CHECKCOMBOBOX Map(CUniCheckComboBox,CCheckComboBox)
- #define MSG_MAP_UNI_ALL \
- MSG_MAP_UNI_EDIT \
- MSG_MAP_UNI_ADDRESS \
- MSG_MAP_UNI_COMBOBOX \
- MSG_MAP_UNI_DATETIMECTRL \
- MSG_MAP_UNI_CHECKCOMBOBOX \
最后,我在一個CPP文件中直接調用 MSG_MAP_UNI_ALL 既完成了宏的消息映射的定義。但是這種方式在VS2005中無法編譯通過,最后我不得不在模板類的頭文件中增加了如下的一個消息映射宏:
- #define BEGIN_TEMPLATE_MESSAGE_MAP_EX(theClass,
type_name1,type_name2, baseClass)- PTM_WARNING_DISABLE
- template < typename type_name1,typename type_name2 >
- const AFX_MSGMAP* theClass< type_name1 ,type_name2 >
GetMessageMap() const- {
- return GetThisMessageMap();
- }
- template < typename type_name1 ,typename type_name2>
- const AFX_MSGMAP* PASCAL theClass
< type_name1 ,type_name2 >GetThisMessageMap()- {
- typedef theClass< type_name1 ,type_name2 > ThisClass;
- typedef baseClass TheBaseClass;
上述的模板類消息映射宏我是參考BEGIN_TEMPLATE_MESSAGE_MAP(theClass, type_name, baseClass)編寫的,該宏只支持一個模板參數,而我定義的模板中需要兩個模板參數,因此,我自己擴充VS2003編譯器一下。關于BEGIN_TEMPLATE_MESSAGE_MAP的幫助在MSDN中好像沒有,在afxwin.h中定義了: