zoukankan      html  css  js  c++  java
  • 派生类继承父类的数据成员探究

    1. 在MFC中用CClientDC这个类来画图,添加OnLButtonUp的消息响应函数,程序如下:
    void CDrawView::OnLButtonUp(UINT nFlags, CPoint point) 
    {
        // TODO: Add your message handler code here and/or call default
        CClientDC dc(this); //在该句的 CClientDC 构造函数中用this,也就是当前CDrawView对象的指针
        dc.MoveTo(m_ptOrigin);
        dc.LineTo(point);
        CView::OnLButtonUp(nFlags, point);
    }

     画出来的效果是这样子的:可以看到,线条根本不可能超出CDrawView的客户区(也就是CDrawView的整个区域)

    2. 我把CClientDC的构造函数参数改变一下,改成用GetParent(), 也就是取View窗口的父窗口,也就是框架窗口Frame的指针

    发现效果是这样的: 画的线条可以超出View窗口,去到框架窗口

    3、我找了一下原因,首先,看看这个CClientDC的构造函数源代码,如下:

    CClientDC::CClientDC(CWnd* pWnd)  // 1   in  File---------WINGDI.CPP
    {
        ASSERT(pWnd == NULL || ::IsWindow(pWnd->m_hWnd)); //  2
    
        if (!Attach(::GetDC(m_hWnd = pWnd->GetSafeHwnd())))  //  3
            AfxThrowResourceException();
    }
    
    CClientDC::~CClientDC()
    {
        ASSERT(m_hDC != NULL);
        ::ReleaseDC(m_hWnd, Detach());
    }

         4、注意画红线的三个地方,首先明确一点,CClientDC当中也有m_hWnd这个数据成员,CWnd当中也有m_hWnd这个句柄数据成员

    class CClientDC : public CDC   //in File-----------AFXWIN.H
    {
        DECLARE_DYNAMIC(CClientDC)
    
    // Constructors
    public:
        CClientDC(CWnd* pWnd);
    
    // Attributes
    protected:
        HWND m_hWnd;
    
    // Implementation
    public:
        virtual ~CClientDC();
    #ifdef _DEBUG
        virtual void AssertValid() const;
        virtual void Dump(CDumpContext& dc) const;
    #endif
    };

    然后,当创建CDrawView对象完成以后,由于CDrawView这个类继承与CView,CView这个类继承自CWnd,而且只有一下几个类含有m_hWnd这个数据成员,如下图,所以CDrawView这个对象的基类不会含有m_hWnd这个数据成员,当CDrawView的当前对象创建完成以后,这个数据成员已经赋值完成,也就是已经把CDrawView这个窗口的句柄传递给了,CDrawView的m_hWnd这个句柄成员。

    因此,看会CClientDC的构造函数, 由于当前CDrawView是CWnd的派生类,因此可以传递this指针给基类,其实也是一种隐式类型转换,派生类指针转化为基类指针,转化后的指针只能指向派生类的基类部分,因为不可能违背pWnd这个指针本身就是基类类型这个事实。然后用

    pWnd->m_hWnd 来获取这个指针所指对象的数据成员,也就是派生类中的基类部分的m_hWnd, 由于m_hWnd已经被赋值,也就是当前CDrawView
    对象窗口的句柄,所以就调用的就是CDrawView窗口句柄。
    下面3处,这种用GetSafeHwnd()来调用主要是为了安全起见,确认一下,当前的指针是否为空,为空就没有句柄。
    
    
    CClientDC::CClientDC(CWnd* pWnd)  
    {
        ASSERT(pWnd == NULL || ::IsWindow(pWnd->m_hWnd)); //  2
    
        if (!Attach(::GetDC(m_hWnd = pWnd->GetSafeHwnd())))  //  3
            AfxThrowResourceException();
    }

     5、最后来解释一下画图出现的两种情况,第一种,用this,就是当前对象的地址,当然就是调用CDrawView的句柄,也可以说绑定了CDrawView的句柄;第二种

    用GetParent()来获取CDrawView的父窗口的句柄,就是绑定了MainFram窗口的句柄,而由于MainFrame窗口的客户区包括工具栏,因此也就可以把线画到工具栏上。

          谢谢阅读,请指正。

  • 相关阅读:
    java基础梳理--朝花夕拾(三)
    java基础梳理--朝花夕拾(二)
    [C++] 分治法之棋盘覆盖、循环赛日程表
    [C++] 递归之全排列问题、半数集
    蓝桥杯 算法训练 ALGO-143 字符串变换
    蓝桥杯 算法训练 ALGO-129 特殊的数字四十
    蓝桥杯 算法训练 ALGO-126 水仙花
    蓝桥杯 算法训练 ALGO-122 未名湖边的烦恼
    蓝桥杯 算法训练 ALGO-121 猴子分苹果
    蓝桥杯 算法训练 ALGO-116 最大的算式
  • 原文地址:https://www.cnblogs.com/develop-me/p/5742759.html
Copyright © 2011-2022 走看看