ATL、MFC、WTL CString 的今生前世

话说CString这个东西困扰了很多年轻人,因为它会引起诡异的编译错误,今天跟着我一起来深入ATL、WTL头文件,来把这个东西搞个清清楚楚。

涉及到头文件

  ATL : atlstr.h, atlsimpstr.h

  MFC : cstringt.h、afxstr.h

  WTL : atlmisc.h

  ATL和MFC有关剪不断理还乱的关系,为了更容易分析,我们先要理清这四个头文件间的关系。观察相互间观察顺序,可以得出:

  atlstr.h引用cstringt.h,cstring引用atlsimpstr.h,afxstr.h引用cstringt.h,由此可得出下图:

 

atlsimpstr.h 都干了什么

  1、定义了 CStringData 和 CNilStringData 类(前篇已述,此处略)

  2、定义了 ChTraitsBase 类,类如下:

     

  此类比较简单,功能是为不同的字符类型,建立新的统一的名称。另外,这里使用到了模板特化技术。

     3、定义了CSimpleStringT类,此类的功能是,在ChTraitBase定义的统一名称的基础上,提供字符串一些基本的操作功能函数。

  

      t_bMFCDLL可无视。另外,注意,此处所操作的字符串对象,都是CStringData(前篇已述)

  总述:在atlsimpstr.h中,我们发现了3个令人感兴趣的东西,CStringData 是字符串操作单元,ChTraitBase提供字符串变量统一命名服务,而CSimpStringT是一个基于CStringData字符串操作单元的简易的CString(注意,只是简易,其中并未提供我们常用的CString中的那些函数)。

cstringt.h 都干了什么

  1、定义了 ChTraitsCRT 类,如下:

  

  该类继承atlsimpstr.h中的 ChTraitsBase 类,然后在父类提供服务的基础上,提供一系列字符串底层操作函数。思考:为什么此处用继承?而CSimpleStringT使用提typedef?

  2、定义了 _MFCDLLTraitsCheck 类,如下:

  

   这里再一次用到了模板特化技术,该类用于检测当前使用的StringTraits是ATL定义的还是MFC定义的。(ATL定义的叫StrTraitATL,MFC定义的叫StrTraitMFC,后面会提到)

  3、定义了 CStringT 类,如下:

  

   注意了,CStringT 就是CString的真身!前面说到,CSimpStringT操作CStringData字符串操作单元,提供基本的字符串操作功能,而CStringT继承CSimpleStringT,利用StringTraits,包装更高级的功能函数。而这些更高级的功能函数,就是我们通常调用CString时所使用到的那些函数。

atlstr.h 都干了什么

  1、定义了 CAtlStringMgr 类。(前文已述)

  2、定义了 ChTraitsOS 类,如下:

  

  和 ChTraitCRT相对应,ChTraitsOS继承atlsimpstr.h中的 ChTraitsBase 类,然后在父类提供服务的基础上,提供一系列字符串底层操作函数。

      和 ChTraitCRT相比,他俩提供的函数大部相关,少数不同,另外相同函数名的实现不一定相同。

  3、定义了 StrTraitATL 类,如下:

  

  和 StrTraitMFC相对应,该类提供字符串资源管理函数和CStringData内存管理器的ATL版。

  4、定义了CSTRING,如下:

  

afxstr.h 都干了什么

  1、定义了 StrTraitMFC,如下:

  

  上文已述,和StrTraitATL相对,本类提供的功能实现都封闭在MFC中。

  2、定义了CString,如下:

  

atlmisc.h 都干了什么

  打开atlmisc.h,可以发现此文件只不过是定义了一些结构体,定义了一个CString的简易版。因为ATL CString依赖于MFC头文件,所以,如果在使用CSTRING而又不想加入过多其它文件时,WTL CSTRING提供了一个很好的选择。

  所有文件都分析后,我们发现,atl、mfc、wtl分别定义了一个CString。其中atl和mfc中的CString都是基于CStringT,只有一个地方是不同的,即CStringT所引用的StringTrait(即StrTraitsATL 还是 StrTraitMFC)。而WTL CString 的实现是独立的,是一个真正的类。另外 ,StringTrait引用的Iterator是可选的(即底层字符串操作封装)。

上文分析了ATL、MFC CString的设计和实现,我们不禁会疑问,为什么ATL和MFC的CString头文件要搅在一起?

上文的分析有些杂乱,我们通过一张图来更加清晰的观察,如下:

  上图中,用圈圈住的头文件表示ATL头文件,没被圈的代表MFC头文件。另外,在头文件旁边字符,表示各个头文件中实现的类。

  现在让我们仔细观看,整个貌似平衡的设计中,其实有着很多的不平衡。我想问:

  1、为什么MFC头文件cstringt.h要包含atl头文件atlsimpstr.h?为什么ATL头文件要包含cstringt.h?ATL搞ATL的,MFC搞MFC的,各不相干,起不更好?

  2、ChTraitOS 放在 atlstr.h 中,而 ChTraitCRT 放在 cstringt.h中,他俩功能是类似的,逻辑上是相对的,为神马在文件层次上却不对齐,要如此的别扭?

  话说中国人看待问题的时候,往往把某一大类看作一蹴而就的完美的整体。譬如Tencent很赚钱,很大,产品推出快,人们就认为Tencent内部有着良好的组织架构。这里我要告诉大家的是,任何大规模的东西,都是一点一滴积累起来的。ATL也是,MFC也是。这两个东西不是一个月、两个月的开发就成了现在的样子的,他们都是逐步叠加,逐步改进才成了今天这个强大的库的。扯了这些,是要告诉大家,要以变化、积累、动态来看待和分析事物的衍生。

  好了,现在我们来看为什么微软会搞出这么别扭的结构。

  话说,某一天ATL开发小组发现老是操作char,太低效,STL的string也不是很好用,于是乎,他们做了一个为ATL服务的简单的字符串类,名字叫 CSimpleStringT,通过typedef,定义成了 CSimpleString。

  后天某一天,MFC的人也发现char和string超不好用,他们发现公司的ATL小组已经做了一个成熟CSimpleString类,于是MFC小组拿来直接使用。在使用中,MFC小组的人发现CSimpleString做的太简单了,有很多的功能,它都不提供,另外,类函数设计的也不好用。于是MFC小组的成员决定扩展CSimpleString,他们将扩展的代码写进cstringt.h中,另外抽离出对外的接口头文件afxstr.h,将定义放在了这。(到这里,我们发现了上面提到问题的发生点,MFC的头文件继承了ATL头文件)。

  又到后来,MFC小组的某个成员(主程级)转到了ATL小组,来到ATL小组后,他发现,平日用惯了CString,现在要用CSimpleString真TM憋屈,于是他建议在ATL中自封装一个CStrnig。ATL小组发现,继然MFC的CString已经做得这么成熟稳定且好用了,自己没必要再另起炉灶,另外,他们发现cstringt.h是独立于MFC其它文件的,虽然属于MFC小组(MFC小组所写),但是引用的却都是atl的头文件,因此,引用cstringt.h不会融入MFC其它旁大的文件,因此可行。所以综合以上考虑,ATL小组直接继承于cstringt头文件,派生了自己的CString,放在了atlstr.h中。(注意,连名字取得都和afxstr.h相对应,到这里,我们又看到,ATL头文件继承了MFC头文件)。

  就这样,诞生了两份CSring。日子很平淡的一天一天过去,直到有一天,有个项目要混用ATL和MFC,他们发现,有两份CString,编译不过!因为ATL的CString毕竟只是模仿MFC,于是ATL让路,加上了宏定义 #ifndef _AFX ,意即,在没有使用MFC时,ATL才定义CString。

  ATL 和 MFC CString的故事讲完了,相信大家对CString相关文件目前结构的来龙去脉应该很清楚了。但是WTL呢?为什么WTL也要定义一个CString?话说WTL编写过程中,WTL组的后生小辈们看了ATL的CString代码,他们觉得咋这CString搞得咋这么复杂呢?看得头都大了,于是他们设计了一个四两拨千斤的CString,不继承任何东西,不依赖任何东西,就是一个简简单单的类。在初期,他们工作得很好,但是到后期,他们发现,如果两个人的代码用的是不同的CString的话,那么将代码合并的时候,编译不过,和之前遇到的问题一样,会产生两个CString,于是WTL不得不加了另外一个宏 _WTL_NO_CSTRING 来禁止WTL CString的编译。

  好了,故事全都讲完了,ATL、WTL、MFC,结论是,先有CAtlSimpleString,后有MFC CString,再有ATL CString,最后有WTL CString,唉,微软的人搞这么复杂干嘛呢……

  现在,还遗留一个问题,WTL、ATL、MFC,哪个CString效率高一些呢?欲知结果,待哥下回分析。

目录 WTL for MFC Programmers, Chinese Version Prologue WTL for MFC Programmers, Chinese Version PrologueWTL for MFC Programmers, Chinese Version Prologue WTL for MFC Programmers, Chinese Version Prologue WTL for MFC Programmers, Chinese Version Prologue WTL for MFC Programmers, Chinese Version PrologueWTL for MFC Programmers, Chinese Version PrologueWTL for MFC Programmers, Chinese Version Prologue WTL for MFC Programmers, Chinese Version PrologueWTL for MFC Programmers, Chinese Version Prologue WTL for MFC Programmers, Chinese Version Prologue WTL for MFC Programmers, Chinese Version PrologueWTL for MFC Programmers, Chinese Version PrologueWTL for MFC Programmers, Chinese Version PrologueWTL for MFC Programmers, Chinese Version Prologue WTL for MFC Programmers, Chinese Version PrologueWTL for MFC Programmers, Chinese Version PrologueWTL for MFC Programmers, Chinese Version PrologueWTL for MFC Programmers, Chinese Version Prologue WTL for MFC Programmers, Chinese Version PrologueWTL for MFC Programmers, Chinese Version PrologueWTL for MFC Programmers, Chinese Version PrologueWTL for MFC Programmers, Chinese Version PrologueWTL for MFC Programmers, Chinese Version Prologue WTL for MFC Programmers, Chinese Version Prologue WTL for MFC Programmers, Chinese Version Prologue WTL for MFC Programmers, Chinese Version PrologueWTL for MFC Programmers, Chinese Version Prologue WTL for MFC Programmers, Chinese Version Prologue WTL for MFC Programmers, Chinese Version Prologue ................................ ........................... 6 WTL for MFC Programmers, Part I - ATL GUI Classes ................................ ........................... 8 README.TXTREADME.TXT README.TXTREADME.TXT README.TXTREADME.TXT ................................ ................................ ................................ ......................... 8 对本系列文章的总体介绍 对本系列文章的总体介绍 对本系列文章的总体介绍 ................................ ................................ ................................ ....... 9 对第一章的简单介绍 对第一章的简单介绍 ................................ ................................ ................................ ............. 11 ATL ATL ATL 背景知识 ................................ ................................ ................................ ....................... 11 ATLWTL 的发展历史 ................................ ................................ ......................... 12 ATL-style 模板 ................................ ................................ ................................ ............. 12 ATL ATL ATL 窗口类 ................................ ................................ ................................ ........................... 15 定义一个窗口的实现 定义一个窗口的实现 ................................ ................................ ................................ ............. 17 填写消息映射链 ................................ ................................ ................................ ............. 19 高级消息映射链和嵌 高级消息映射链和嵌 入类 ................................ ................................ ................................ ..... 21 ATLATL 程序的结构 ................................ ................................ ................................ .................... 24 ATLATL 中的对话框 ................................ ................................ ................................ .................... 27 WTL for MFC Programmers, Part II - WTL GUI Base Classes ................................ ............. 32 对第二部分的介绍 对第二部分的介绍 ................................ ................................ ................................ ................. 32 WTL WTL WTL WTL 总体印象 ................................ ................................ ................................ ...................... 32 开始写 WTLWTLWTL程序 ................................ ................................ ................................ .................. 33 WTL WTL WTL WTL 对消息映射的增强 ................................ ................................ ................................ ...... 36 从 WTLWTLWTL的应用程序生成向导能得到什么 的应用程序生成向导能得到什么 的应用程序生成向导能得到什么 ................................ ................................ .......... 42 使用向导的整个过程 ................................ ................................ ................................ ..... 42 查看生成的代码 ................................ ................................ ................................ ............. 44 CMessageLoop CMessageLoop CMessageLoop CMessageLoop CMessageLoop CMessageLoop CMessageLoop CMessageLoop 的内部实现 ................................ ................................ ................................ .. 47 CFrameWindowImpl CFrameWindowImpl CFrameWindowImpl CFrameWindowImpl CFrameWindowImpl CFrameWindowImpl CFrameWindowImpl CFrameWindowImpl CFrameWindowImpl CFrameWindowImpl CFrameWindowImpl CFrameWindowImpl CFrameWindowImpl 的内部实现 ................................ ................................ ......................... 48 回到前面的时钟程序 回到前面的时钟程序 ................................ ................................ ................................ ............. 50 界面元素的自动更新 界面元素的自动更新 (UI Updating)(UI Updating)(UI Updating)(UI Updating) (UI Updating) (UI Updating)(UI Updating)(UI Updating)(UI Updating) (UI Updating) ................................ ................................ ...................... 51 添加控制时钟的新菜单项 ................................ ................................ ............................. 52 调用 UIEnable()................................ ................................ ................................ ............ 53 消息映射链中最后需要注意的地方 消息映射链中最后需要注意的地方 消息映射链中最后需要注意的地方 消息映射链中最后需要注意的地方 ................................ ................................
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值