rFxn) \
{ message, 0, 0, 0, AfxSig_lwl, \
(AFX_PMSG)(AFX_PMSGW) \
(static_cast< LRESULT (AFX_MSG_CALL CWnd::*)(WPARAM, LPARAM) > \
(memberFxn)) },
注意,函数类型没有变化,都是:
LRESULT (AFX_MSG_CALL CWnd::*)(WPARAM, LPARAM);
类型的函数指针(CWnd以及派生类的类成员函数指针),区别之处是新的ON_MESSAGE宏使用C++的static_cast 操作符代替了C类型的强制转换。产生这两个错误其实是因为用户没有按照ON_MESSAGE宏的约定声明和定义消息响应函数造成的,比如,对于某些不需要处理返回值的消息响应函数,用户通常这样声明和定义消息响应函数:
在头文件中声明:
afx_msg void OnFileProcess(WPARAM wParam,LPARAM lParam);
在源文件中实现:
void CCrpFileOpavDlg::OnFileProcess(WPARAM wParam, LPARAM lParam)
{
.......
}
或者更过分一些,直接指定为实际参数类型:
在头文件中声明:
afx_msg void OnFileProcess(LPCTSTR lpszMessage, int nPercent);
在源文件中实现:
void CCrpFileOpavDlg::OnFileProcess(LPCTSTR lpszMessage, int nPercent)
{
.......
}
旧版本的ON_MESSAGE使用了C类型的强制转换,宏解开后的代码后不会产生错误信息,但是改成对类型检查很严格的static_cast 操作符时就出问题了,因为通不过static_cast 操作符的检查。解决方法就是修改代码,同时吸取教训,普遍使用的方法并不一定就能约定俗成,一切还是要按照规矩来。
错误现象之三:
f:\project\.....\WzButton.cpp(74) : error C2440: 'static_cast' : cannot convert from 'UINT (__thiscall CWzButton::* )(CPoint)' to 'LRESULT (__thiscall CWnd::* )(CPoint)'
Cast from base to derived requires dynamic_cast or static_cast
出现这个错误的原因可是“人力不可抗拒”之原因造成的,因为旧版本的ON_WM_NCHITTEST 宏使用了
UINT (__thiscall CWzButton::* )(CPoint);
类型的类成员函数指针,其定义如下:
#define ON_WM_NCHITTEST() \
{ WM_NCHITTEST, 0, 0, 0, AfxSig_wp, \
(AFX_PMSG)(AFX_PMSGW)(UINT (AFX_MSG_CALL CWnd::*)(CPoint))&OnNcHitTest },
但是新版本变成了:
#define ON_WM_NCHITTEST() \
{ WM_NCHITTEST, 0, 0, 0, AfxSig_l_p, \
(AFX_PMSG)(AFX_PMSGW) \
(static_cast< LRESULT (AFX_MSG_CALL CWnd::*)(CPoint) > (&ThisClass :: OnNcHitTest)) },
注意返回值类型由UINT改成了LRESULT,再加上static_cast的严格检查,所以就出错了。修改的方法就是将你的OnNcHitTest函数由:
afx_msg UINT OnNcHitTest(CPoint point);
改成:
afx_msg LRESULT OnNcHitTest(CPoint point);
不必太在意,这个不是你的错,不过,如果你要维护一个老的界面库(通常很多控件的subclass都会用到ON_WM_NCHITTEST),改起来还是很痛苦地,不扯了,继续下一个。
七、statreg.cpp 和atlimpl.cpp 的废弃(obsolete)问题
在编译老的ATL向导生成的代码时,会遇到下面的编译输出:
StdAfx.cpp
statreg.cpp is obsolete. Please remove it from your project.
atlimpl.cpp is obsolete. Please remove it from your project.
因为老的ATL向导生成的代码通常在stdafx.cpp文件中添加以下代码:
#ifdef _ATL_STATIC_REGISTRY
#include
#include
#endif
#include
根据提示删除#include 和#include 两行代码就行了,不过更好的办法是这样改:
#ifdef _ATL_STATIC_REGISTRY
#include
#if _MSC_VER <= 1200 // MFC 6.0 or earlier
#include
#endif
#endif
#if _MSC_VER <= 1200 // MFC 6.0 or earlier
#include
#endif
八、新的C++编译器不再支持默认类型的变量定义
错误现象是:
f:\project\.....\WzCheckBox.cpp(464) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
产生这个错误的原因是程序中出现了这样的代码:
const some_const_var = 10;
或
static some_static_bool = FALSE;
新的C++编译器严格按照C++标准,不再支持默认类型的变量定义方式,必须严格指定变量类型,如下使用:
const int some_const_var = 10;
或
static BOOL some_static_bool = FALSE;
九、for 语句的变量作用域问题
考察下面的代码:
for(int i = 0; i < 120; i++)
{
if(something_happen)
{
break;
}
.............
}
if(i < 120)
{
//something happen
}
在VC6的编译器中,这样的代码是没有问题的,因为VC6的编译器为了兼容旧的Microsoft C/C++编译器,没有严格按照C++标准执行,但是从VC7开始,VC的编译器开始遵守C++标准,所以就会出现“变量i没有定义的错误”。解决的方法也很简单,按照Jim Hyslop 和Herb Sutter的经典对话系列的第四篇中的方法,改成如下就可以了:
int i;
for(i = 0; i < 120; i++)
十、字符串函数的返回值问题
strchr(_tcschr)、strpbrk(_tcspbrk)、strrchr(_tcsrchr)和strstr(_tcsstr)这四个函数在VC6的CRT库中定义的返回值都是char *(TCHAR *) (#add 括号里和括号外的也是依次对应 |