2005和6.0
今天运行了一下以前做的五子棋的程序,以前是用6.0编译的,但是放在2005下。编译却通不过,提示错误为 error C2440: “static_cast”: 无法从“void (__thiscall CFiveChessDlg::* )(CPaintDC &)”转换为“AFX_PMSG”。
错误发生在 ON_BN_CLICKED(IDC_RESTART, OnRestart) 这个宏,它是点击按钮的一个响应事件。它定义为
#define ON_BN_CLICKED(id, memberFxn) \
ON_CONTROL(BN_CLICKED, id, memberFxn)。
ON_CONTROL(BN_CLICKED, id, memberFxn) 又是一个宏定义,它的定义为
#define ON_CONTROL(wNotifyCode, id, memberFxn) \
{ WM_COMMAND, (WORD)wNotifyCode, (WORD)id, (WORD)id, AfxSigCmd_v, \
(static_cast< AFX_PMSG > (memberFxn)) },
OnRestart 这个函数声明为afx_msg void OnRestart(CPaintDC &dc),它是通过BEGIN_MESSAGE_MAP把消息添加到消息映射表。
我猜想发生此事的原因是,AFX_PMSG 定义为
typedef void (AFX_MSG_CALL CCmdTarget::*AFX_PMSG)(void); 它是一个无参的函数。然而我们的OnRestart是一个有一个参数的函数,所以2005在编译的时候进行参数匹配的时候发现了程序的不正确,所以报错了。
那么6.0为什么没有报错呢?我猜想是因为,它对于宏没有那么高的安全识别。我自身是没有参数的,但是你给我传进入一个参数,我只是不用就OK了,不会影响到到程序运行的正确性。然而,我感觉还是2005的做法是正确的,因为咱们现在是多传参数。如果少传参数而不报错的话,那么想找出这个bug,那就劳民伤财了。
这个问题的解决办法,就是把参数去掉。