具有多重继承的Message Map MFC:如何避免警告C4407和运行时崩溃 [英] Message Map MFC with multiple inheritance: how to avoid warning C4407 and runtime crashes

查看:145
本文介绍了具有多重继承的Message Map MFC:如何避免警告C4407和运行时崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近将一个项目从VS2008移植到VS2013,并遇到了一些堆栈损坏的问题. 经过一番研究,我可以将原因定位在以下代码上:

class CInternalInterface
{
  afx_msg void OnMouseMove(UINT, CPoint) = 0; 
};
class CMyDlg : public CDialog, public CInternalInterface
{
  afx_msg void OnMouseMove(UINT, CPoint); 
}
BEGIN_MESSAGE_MAP(CMyDlg, CDialog)
  ON_WM_MOUSEMOVE()
END_MESSAGE_MAP()

编译器在 ON_WM_MOUSEMOVE()语句和运行时堆栈上发出警告C4407:在指向成员表示的不同指针之间进行转换,编译器可能会生成不正确的代码" 每当处理WM_MOUSEMOVE消息时都会损坏.

尽管我同意在非CWnd派生的接口中定义MFC消息处理程序函数最初不是一个好主意,但该代码在VS2008上运行良好(无警告,没有运行时问题). >

现在,我通过为OnMouseMove处理程序使用不同的函数名称显式扩展ON_WM_MOUSEMOVE来解决此问题

...
class CMyDlg : public CDialog, public CInternalInterface
{
  afx_msg void OnCWndMouseMove(UINT, CPoint); 
  afx_msg void OnMouseMove(UINT, CPoint); 
}
BEGIN_MESSAGE_MAP(CMyDlg, CDialog)
  {
    WM_MOUSEMOVE, 0, 0, 0, AfxSig_vwp, 
     (AFX_PMSG)(AFX_PMSGW) 
     (static_cast< void (AFX_MSG_CALL CWnd::*)(UINT, CPoint) >(&CMyDlg::OnCWndMouseMove))
  },    
END_MESSAGE_MAP()

但是,此解决方案有几个缺点-扩展宏可能会导致与将来的MFC版本不兼容,并且可能使其他开发人员使MFC消息处理程序使用不同的名称.

所以我有2个问题:

  1. 这是编译器错误吗?只要CWnd派生基类是类定义中列出的第一个基类,多重继承就不应该与MFC一起使用吗?该宏将函数显式转换为CWnd :: *,因此两个OnMouseMove(...)函数之间应该没有歧义.

  2. 是否有更好的解决方法?在CInternalInterface中重命名OnMouseMove()是不可行的,因为它在代码库中大量使用,并且判断何时调用重命名的函数以及何时在各种实现中使用OnMouseMove并非易事.

解决方案

只是一种不同的方法.使用消息映射无法直接解决您的问题.

您为什么不对此类接口"使用经典子类化?

我使用CSubclassWnd(来自Paul DiLascia),CHookWnd(来自PJ Naughter)或仅使用ATL子类化功能.

这可以帮助我将接口附加到现有窗口,并且可以根据特定的窗口操作实现标准功能...

使用上面的库之一,您甚至可以在一个窗口上拥有多个接口".

I recently ported a project from VS2008 to VS2013 and ran into some stack corrupt issues. After some research I could pinpoint the cause to the following code:

class CInternalInterface
{
  afx_msg void OnMouseMove(UINT, CPoint) = 0; 
};
class CMyDlg : public CDialog, public CInternalInterface
{
  afx_msg void OnMouseMove(UINT, CPoint); 
}
BEGIN_MESSAGE_MAP(CMyDlg, CDialog)
  ON_WM_MOUSEMOVE()
END_MESSAGE_MAP()

The compiler issued a "warning C4407: cast between different pointer to member representations, compiler may generate incorrect code" at the ON_WM_MOUSEMOVE() statement and at runtime the stack got corrupted whenever the WM_MOUSEMOVE message was processed.

The code ran fine with VS2008 (no warning, no runtime issues), although I agree that defining an MFC message handler function in a non-CWnd-derived interface wasn't a good idea in the first place.

For now I resolved it by expanding the ON_WM_MOUSEMOVE explicitely using a different function name for OnMouseMove handler

...
class CMyDlg : public CDialog, public CInternalInterface
{
  afx_msg void OnCWndMouseMove(UINT, CPoint); 
  afx_msg void OnMouseMove(UINT, CPoint); 
}
BEGIN_MESSAGE_MAP(CMyDlg, CDialog)
  {
    WM_MOUSEMOVE, 0, 0, 0, AfxSig_vwp, 
     (AFX_PMSG)(AFX_PMSGW) 
     (static_cast< void (AFX_MSG_CALL CWnd::*)(UINT, CPoint) >(&CMyDlg::OnCWndMouseMove))
  },    
END_MESSAGE_MAP()

This solution however has several drawbacks - expanding the macro may cause incompatibilities with future MFC versions and it may confuse other developers to have the MFC message handler using a different name.

So I have 2 questions:

  1. Is this a compiler error ? Isn't multiple inheritance supposed to work with MFC as long as the CWnd derived base class is the first one listed in the class definition ? The macro explicitly casts the function to a CWnd::* so there should be no ambiguity between the two OnMouseMove(...) functions.

  2. Is there a better way to resolve it? Renaming the OnMouseMove() in CInternalInterface is not feasible, as it is heavily used in the code base and judging when to call the renamed function and when to use OnMouseMove in the various implementations is not trivial.

解决方案

Just a different approach. It is not solving your problem with the messages maps directly.

Why don't you use classic subclassing for such an "interface"?

I use CSubclassWnd (from Paul DiLascia), CHookWnd (from PJ Naughter) or just the ATL subclassing features.

This helps me to attach an interface to an existing window and I can implement standard function upon the specific window actions...

Using one of the libraries above you can even more than one "interface" to a window.

这篇关于具有多重继承的Message Map MFC:如何避免警告C4407和运行时崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆