关于 ATL 中 CComControl 的构造

 

分享一篇 C++语言 & ATL 的高阶解读笔记,你需要在C++语言特性中上串下跳,应该算篇有质量的文章。

  

class ATL_NO_VTABLE CHello :

   // ...

   public CComControl<CHello>

{

   // ...

}

叶子类,继承CComControl,将自己作为模板参数传入。(ATL贯彻全场的静态多态技巧)

 

template <class T, class WinBase =  CWindowImpl< T > >

class ATL_NO_VTABLE CComControl : public CComControlBase, public WinBase

{

public:

   CComControl() : CComControlBase(m_hWnd) {}

   // ...

}

CComControl有个默认模板参数CWindowImpl,而CWindowImpl也使用叶子类作为其模板参数。

 

在初始化列表中CComControlBase使用的m_hWnd来得有点妖怪:

m_hWnd是WinBase带来的(多重继承)

m_hWnd这时候没有 有效的值

因为 子对象CComControlBase 先于 子对象WinBase构造,而 子对象WinBase 只是分配了内存(见下条解释)

这里违背了“按声明次序使用”的原则,使用了没有初始化的成员,进入危险地带。

m_hWnd这时候 有 有效的内存空间。

 因为叶子对象CHello已经分配了空间,正在通过 构造函数 建立各成员变量的初值。

尽管CComControlBase使用了一个没有初始化的、叶子类带来的成员变量,但小心使用依然有效。

 

class ATL_NO_VTABLE CComControlBase

{

public:

   CComControlBase(HWND& h) : m_hWndCD(h)

   {

      memset(this, 0, sizeof(CComControlBase));

      m_phWndCD = &h;

      // ...

   }

   // ...

// Attributes

public:

#pragma warning(push)

#pragma warning(disable: 4510 4610) // unnamed union

   union

   {

      HWND& m_hWndCD;

      HWND* m_phWndCD;

   };

#pragma warning(pop)

// ...

}

 

这里进入CComControlBase神奇的构造函数

它将自己(作为一个子对象)所拥有的内存清零:起始地址this,清零长度自己的大小sizeof(CComControlBase)

注意它的参数是一个引用,这里 传值 与 传引用 将有迥然不同的区别(而不是过去的差不多,主要是优化)

m_phWndCD赋值为 参数的地址。语言特性小考场:由于参数是引用,引用的取地址值,与引用所值对象地址一致。

 

回到CComControl构造函数初始化列表问题,子对象CComControlBase的m_phWndCD现在指向,另一个子对象WinBase中的m_hWnd成员。

 

设计讨论:CComControlBase为使用一个HWND参数,没有进一步使用模板,而是简单的使用一个成员变量。虽然CComControlBase子对象和WinBase子对象都住在一个家中——CHello叶子对象里,CComControlBase应有可能使用模板,进一步的将m_phWndCD所占内存开销去掉。为啥没有呢?是为了避免过多的纠缠、变复杂化(以易于独立思考、理解),还是HWND需要一定的独立性?

 

语言特性弯弯绕绕:再遇union的效用

语言书上说“引用一经复制,便不能修改”,幽暗的世界里这不是事实。此处应该使用了语言实现的一些底层特性,以及Windows编程时的一些命名约定。

匿名union让m_hWndCD与m_phWndCD共用一个内存,通过对m_phWndCD的修改,我们改变了引用m_hWndCD的值!

介于Windows编程的命名约定,我们习惯了m_pXXX == & m_XXX 这样的惯例,此处同样成立

&m_hWndCD == m_phWndCD

*m_phWndCD == m_hWndCD

有点抓狂,对同一个内存的两种访问方法,居然得到相同的值,更有甚者 m_hWndCD == m_hWnd,这绝对是对C++语言意志力的考验!

 

本文转载处:http://blog.sina.com.cn/s/blog_843c41c80101h3x9.html

posted @ 2019-10-23 15:04  IceArrow  阅读(268)  评论(0编辑  收藏  举报