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

关于 ATL 中 CComControl 的构造的更多相关文章

  1. ATL中窗口句柄与窗口过程的关联方法

    ATL中采用了一种动态生成机器指令的方式进行窗口句柄与窗口对象进行关联,以是详细分析: CWindowImpl会在第一次调用Create时注册窗口类,该窗口类是的信息是在CWindowImpl的子类中 ...

  2. Scala 深入浅出实战经典 第81讲:Scala中List的构造是的类型约束逆变、协变、下界详解

    王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-97讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...

  3. 理解ATL中的一些汇编代码(通过Thunk技术来调用类成员函数)

    我们知道ATL(活动模板库)是一套很小巧高效的COM开发库,它本身的核心文件其实没几个,COM相关的(主要是atlbase.h, atlcom.h),另外还有一个窗口相关的(atlwin.h), 所以 ...

  4. 第81讲:Scala中List的构造和类型约束逆变、协变、下界详解

    今天来学习一下scala中List的构造和类型约束等内容. 让我们来看一下代码 package scala.learn /** * @author zhang */abstract class Big ...

  5. [Leetcode] Construct binary tree from preorder and inorder travesal 利用前序和中续遍历构造二叉树

    Given preorder and inorder traversal of a tree, construct the binary tree. Note:  You may assume tha ...

  6. ATL中宏定义offsetofclass的分析

    近日学习ATL,通过对宏定义offsetofclass的解惑过程.顺便分析下虚函数表,以及通过虚函数表调用函数的问题. 1 解开ATL中宏定义offsetofclass的疑惑 #define _ATL ...

  7. LeetCode105 从前序和中序序列构造二叉树

    题目描述: 根据一棵树的前序遍历与中序遍历构造二叉树. 注意:你可以假设树中没有重复的元素. 例如,给出 前序遍历 preorder = [3,9,20,15,7] 中序遍历 inorder = [9 ...

  8. Vue中的Xss构造

    首发tools:https://www.t00ls.net/thread-59512-1-1.html 存储型XSS 最近做测试的时候碰到了一个前端页面使用了Vue框架的项目 在测试XSS漏洞的过程中 ...

  9. 在Asp.Net MVC中使用ModelBinding构造Array、List、Collection以及Dictionary

    在asp.net mvc中,我们可以在html表单中使用特定的格式传递参数,从而通过model binder构造一些集合类型. 第一种方式 public ActionResult Infancy(Pe ...

随机推荐

  1. win10序列号 2019年10月测试

    win10序列号 N3415-266GF-AH13H-WA3UE-5HBT4 win10序列号 NPK3G-4Q81M-X4A61-D553L-NV68D win10序列号 N617H-84K11-6 ...

  2. 从零开始学习GDI+ (二) 基本概念与基本操作

    从零开始学习GDI+ (一)我的第一个GDI+程序 上文给新手学习GDI+讲述了vs环境等的准备工作,并且可以直接用GDI+绘图了.本文开始,讲述的可能偏理论,建议学习的过程中大胆尝试,多使用API. ...

  3. Luogu P4147 玉蟾宫

    题目 就是全0子矩阵. 先预处理每个点上面有多少个连续的0(包括自己). 然后我们枚举下边界(1-n). 我们开一个单调栈,记录一个上界递增的矩形集合. 如果我们扫到了一个比当前栈顶要矮的矩形,那么我 ...

  4. python 类(2)

    """ """class BaseCat(object): """ 猫科基础类""&quo ...

  5. QQ音乐爬虫

    #今日目标 **QQ音乐爬虫** 今天要爬取的是QQ音乐任意歌手的所有音乐歌词,因为笔者是周杰伦的忠实粉丝,所以专门写了个爬虫来爬取他的音乐的歌词,因为他的音乐在咪咕音乐可以听,所以便没有去爬取. 好 ...

  6. Mac 基于Anaconda的TensorFlow安装笔记

    最近在中国大学MOOC平台学习北大的曹健老师上的“人工智能实践——Tensorflow”课程,开始我的人工智能之旅.第一天,讲解如何搭建实验室环境,我是mac系统,所以只写mac系统上的实验室环境安装 ...

  7. paramiko : 错误集整理

    错误1    时间2017-12-19:No handlers could be found for logger "paramiko.transport" 解决办法:parami ...

  8. RabbitMQ入门教程(十):队列声明queueDeclare

    原文:RabbitMQ入门教程(十):队列声明queueDeclare 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https:// ...

  9. php小程序生成二维码

    <?php getwxacode(); //生成二维码 function getwxacode(){ $url = "https://api.weixin.qq.com/wxa/get ...

  10. qt tableview列头背景颜色设置

    设置表列头背景颜色 QHeaderView::section { background: rgb(255, 255, 127); }