欢迎来到.net学习网

欢迎联系站长一起更新本网站!QQ:879621940

您当前所在位置:首页 » ASP.Net » 正文

热门阅读

剖析ATL与WTL CString的实现机制

创建时间:2011年06月12日 23:38  阅读次数:(5656)
分享到:

话说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中Y*NW[祂 \W[祂 T饄KN魰O(u&

来源:
说明:所有来源为 .net学习网的文章均为原创,如有转载,请在转载处标注本页地址,谢谢!
【编辑:Wyf

打赏

取消

感谢您的支持,我会做的更好!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

最新评论

共有评论0条
  • 暂无任何评论,请留下您对本文章的看法,共同参入讨论!
发表评论:
留言人:
内  容:
请输入问题 86+90=? 的结果(结果是:176)
结  果: