派生类继承父类的数据成员探究

  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窗口的客户区包括工具栏,因此也就可以把线画到工具栏上。

      谢谢阅读,请指正。

原文地址:https://www.cnblogs.com/develop-me/p/5742759.html