分享一篇 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

最新文章

  1. iOS 开发不可缺少的工具
  2. Oracle下批量将一个用户的所有表的select权限赋值给另外一个用户
  3. [我给Unity官方视频教程做中文字幕]beginner Graphics – Lessons系列之材质了解Materials
  4. C++杂谈(二)初识vector容器与迭代器
  5. hdu 4010 动态树 @
  6. JS手机访问PC端网站自动跳转到手机端网站
  7. BZOJ3755 : Pty爬山
  8. Android loader 详解
  9. Linux网络编程7&mdash;&mdash;使用TCP实现双方聊天
  10. Linux必学的命令
  11. 30 个 Python 语言的特点技巧
  12. 二、WCF应用的通信过程
  13. Merge Two Binary Trees
  14. Redis的使用初探
  15. 解决linux 乌班图下使用eclipse创建类和其他各种操作进程卡死的问题的一种可能方法
  16. eval及json的理解
  17. 使用MagickNet编辑图片
  18. Git 版本管理使用说明。
  19. Docker导入、导出、删除容器
  20. Swift下使用Xib设计界面

热门文章

  1. Java 注解:@PostConstruct和@PreConstruct
  2. CF486B OR in Matrix(构造+思维)
  3. 【转】MySQL-Utilities,mysql工具包
  4. MySQL -3- 基础应用
  5. python生成饼图解决中文乱码
  6. java 环境配置及开发工具
  7. python中常见的一些错误异常类型
  8. dict 小习题
  9. 在Asp.net core使用配置Json创建动态目录树
  10. 正则表达式、原始字符串及re