MFC的派生类多根继承时,为什么必须将MFC类作为第一父类
来源:互联网 发布:薇诺娜淘宝上是正品吗 编辑:程序博客网 时间:2024/06/15 07:31
今天想起一个问题,C++中,如果要实现接口的话,必须使用多重继承机制。MFC中,假如我们有一个类,既需要从MFC窗口类派生,又需要实现我们程序内部的一个接口,例如下面的代码。
如果在这类里添加消息映射函数的话,例如,添加OnLButtonDown消息函数
当点击点击MyDialog激活该消息时会出现异常。
出现这个异常的原因很简单,但是调查过程还是比较难的。很显然这个异常的原因是出现在消息映射部分。
我们看看ON_WM_LBUTTONDOWN()这个宏的定义:
可以看到,MyDialog::OnLButtonDown的函数地址被强制转化为void (AFX_MSG_CALL CWnd::*)(UINT, CPoint)函数类型了。
这样一说就能够完全明白了,对象成员函数的指针类型在使用时必须要2个参数:变量地址和成员函数的地址。MFC函数在调用该函数的时候是这样调用的:
其中mmf.pfn_v_u_p就是MyDialog::OnLButtonDown的地址,而对象的地址(MyDialog对象的地址)被直接当成CWnd的地址了。所以这里要求MFC类必须作为第一个父类。因为当成第二父类的时候,从对象地址到CWnd地址要差一个虚函数表指针的大小,这个虚函数表是第一父类的需函数表(当然,第一父类至少要包含一个virtual函数,不相信这个问题的朋友可以试试在第一父类一个虚函数也不声明,这个时侯就没有这个问题了)。这应该是MFC实现时的疏忽吧,因为可以简单的在DECLARE_MESSAGE_MAP()宏里添加一个虚函数即可:
在调用消息映射函数时改为:
就应该可以了。
- class MyBaseClass
- {
- public:
- virtual ~MyBaseClass(){}
- }
- class MyDialog : public MyBaseClass, public CDialog
- {
- ...
- }
- class MyBaseClass
- {
- public:
- virtual ~MyBaseClass(){}
- }
- class MyDialog : public MyBaseClass, public CDialog
- {
- public:
- DECLARE_MESSAGE_MAP()
- afx_msg void OnLButtonDown(UINT flag, CPoint point);
- }
- //.c文件
- BEGIN_MESSAGE_MAP(MyDialog, CDialog)
- ON_WM_LBUTTONDOWN()
- END_MESSAGE_MAP()
- void MyDialog::OnLButtonDown(UINT flag, CPoint point)
- {
- }
出现这个异常的原因很简单,但是调查过程还是比较难的。很显然这个异常的原因是出现在消息映射部分。
我们看看ON_WM_LBUTTONDOWN()这个宏的定义:
- #define ON_WM_LBUTTONDOWN() /
- { WM_LBUTTONDOWN, 0, 0, 0, AfxSig_vwp, /
- (AFX_PMSG)(AFX_PMSGW) /
- (static_cast< void (AFX_MSG_CALL CWnd::*)(UINT, CPoint) > ( &ThisClass :: OnLButtonDown)) },
这样一说就能够完全明白了,对象成员函数的指针类型在使用时必须要2个参数:变量地址和成员函数的地址。MFC函数在调用该函数的时候是这样调用的:
- (this->*mmf.pfn_v_u_p)(static_cast<UINT>(wParam), point);
- #define DECLARE_MESSAGE_MAP() /
- MFC_DECLARE_MESSAGE_MAP(); /
- virtual GetMFCObject(){return (CObject*)this;}
- (this->GetMFCObject()->*mmf.pfn_v_u_p)(static_cast<UINT>(wParam), point);
- MFC的派生类多根继承时,为什么必须将MFC类作为第一父类
- MFC类继承图
- 派生类的继承
- MFC 窗口框架类CFrameWnd的派生类CMainFrame类
- vs2010 mfc中添加基类CPropertySheet的派生类
- 关于classwizard识别部分MFC派生类的问题
- MFC中创建或派生基于CWnd的类
- CWinThread线程派生类MFC多线程框架
- MFC模板CArray及其派生类
- [MFC] CDC三大派生类
- [MFC]设备环境CDC类及其派生
- 【框架-MFC】CView(chenlu1):MFC在CView的派生类中实现打印和打印预览
- 从MFC类继承的基本方式
- MFC CWinApp派生类中使用CFrameWnd派生类的成员函数Create来创建窗口
- 为什么将派生类声明为父类的友元类?或者相反
- MFC 类继承关系图
- MFC类继承层次图
- MFC类继承关系图
- 第6章 装饰模式
- ACE学习手记--- 智能指针(ACE_Auto_Ptr / ACE_Refcounted_Auto_Ptr)
- java修饰符权限
- gcc编译文件时找不到指定函数怎么办
- 利用多核多线程进行程序优化
- MFC的派生类多根继承时,为什么必须将MFC类作为第一父类
- VERIFY( 1 == InitSkinMagicLib(AfxGetInstanceHandle(), NULL, NULL, NULL)); 老是出错
- java配置环境变量
- 软件项目中的风险识别的思考
- 如何在Windows的cmd下让程序在后台执行
- The four number game
- when you access http://192.88.88.37:81 ,I nat it to 192.88.88.193:80
- boost thread tutorial
- makefile中伪目标详解