新聞中心
話(huà)說(shuō)CString這個(gè)東西困擾了很多年輕人,因?yàn)樗鼤?huì)引起詭異的編譯錯(cuò)誤,今天跟著我一起來(lái)深入ATL、WTL頭文件,來(lái)把這個(gè)東西搞個(gè)清清楚楚。

超過(guò)10年行業(yè)經(jīng)驗(yàn),技術(shù)領(lǐng)先,服務(wù)至上的經(jīng)營(yíng)模式,全靠網(wǎng)絡(luò)和口碑獲得客戶(hù),為自己降低成本,也就是為客戶(hù)降低成本。到目前業(yè)務(wù)范圍包括了:成都做網(wǎng)站、成都網(wǎng)站建設(shè)、成都外貿(mào)網(wǎng)站建設(shè),成都網(wǎng)站推廣,成都網(wǎng)站優(yōu)化,整體網(wǎng)絡(luò)托管,微信小程序定制開(kāi)發(fā),微信開(kāi)發(fā),APP應(yīng)用開(kāi)發(fā),同時(shí)也可以讓客戶(hù)的網(wǎng)站和網(wǎng)絡(luò)營(yíng)銷(xiāo)和我們一樣獲得訂單和生意!
【涉及到頭文件】
ATL : atlstr.h, atlsimpstr.h
MFC : cstringt.h、afxstr.h
WTL : atlmisc.h
ATL和MFC有關(guān)剪不斷理還亂的關(guān)系,為了更容易分析,我們先要理清這四個(gè)頭文件間的關(guān)系。觀(guān)察相互間觀(guān)察順序,可以得出:
atlstr.h引用cstringt.h,cstring引用atlsimpstr.h,afxstr.h引用cstringt.h,由此可得出下圖:
【atlsimpstr.h 都干了什么】
1、定義了 CStringData 和 CNilStringData 類(lèi)(前篇已述,此處略)
2、定義了 ChTraitsBase 類(lèi),類(lèi)如下:
此類(lèi)比較簡(jiǎn)單,功能是為不同的字符類(lèi)型,建立新的統(tǒng)一的名稱(chēng)。另外,這里使用到了模板特化技術(shù)。
3、定義了CSimpleStringT類(lèi),此類(lèi)的功能是,在ChTraitBase定義的統(tǒng)一名稱(chēng)的基礎(chǔ)上,提供字符串一些基本的操作功能函數(shù)。
t_bMFCDLL可無(wú)視。另外,注意,此處所操作的字符串對(duì)象,都是CStringData(前篇已述)
總述:在atlsimpstr.h中,我們發(fā)現(xiàn)了3個(gè)令人感興趣的東西,CStringData 是字符串操作單元,ChTraitBase提供字符串變量統(tǒng)一命名服務(wù),而CSimpStringT是一個(gè)基于CStringData字符串操作單元的簡(jiǎn)易的CString(注意,只是簡(jiǎn)易,其中并未提供我們常用的CString中的那些函數(shù))。
【cstringt.h 都干了什么】
1、定義了 ChTraitsCRT 類(lèi),如下:
該類(lèi)繼承atlsimpstr.h中的 ChTraitsBase 類(lèi),然后在父類(lèi)提供服務(wù)的基礎(chǔ)上,提供一系列字符串底層操作函數(shù)。思考:為什么此處用繼承?而CSimpleStringT使用提t(yī)ypedef?
2、定義了 _MFCDLLTraitsCheck 類(lèi),如下:
這里再一次用到了模板特化技術(shù),該類(lèi)用于檢測(cè)當(dāng)前使用的StringTraits是ATL定義的還是MFC定義的。(ATL定義的叫StrTraitATL,MFC定義的叫StrTraitMFC,后面會(huì)提到)
3、定義了 CStringT 類(lèi),如下:
注意了,CStringT 就是CString的真身!前面說(shuō)到,CSimpStringT操作CStringData字符串操作單元,提供基本的字符串操作功能,而CStringT繼承CSimpleStringT,利用StringTraits,包裝更高級(jí)的功能函數(shù)。而這些更高級(jí)的功能函數(shù),就是我們通常調(diào)用CString時(shí)所使用到的那些函數(shù)。
【atlstr.h 都干了什么】
1、定義了 CAtlStringMgr 類(lèi)。(前文已述)
2、定義了 ChTraitsOS 類(lèi),如下:
和 ChTraitCRT相對(duì)應(yīng),ChTraitsOS繼承atlsimpstr.h中的 ChTraitsBase 類(lèi),然后在父類(lèi)提供服務(wù)的基礎(chǔ)上,提供一系列字符串底層操作函數(shù)。
和 ChTraitCRT相比,他倆提供的函數(shù)大部相關(guān),少數(shù)不同,另外相同函數(shù)名的實(shí)現(xiàn)不一定相同。
3、定義了 StrTraitATL 類(lèi),如下:
和 StrTraitMFC相對(duì)應(yīng),該類(lèi)提供字符串資源管理函數(shù)和CStringData內(nèi)存管理器的ATL版。
4、定義了CSTRING,如下:
【afxstr.h 都干了什么】
1、定義了 StrTraitMFC,如下:
上文已述,和StrTraitATL相對(duì),本類(lèi)提供的功能實(shí)現(xiàn)都封閉在MFC中。
2、定義了CString,如下:
【atlmisc.h 都干了什么】
打開(kāi)atlmisc.h,可以發(fā)現(xiàn)此文件只不過(guò)是定義了一些結(jié)構(gòu)體,定義了一個(gè)CString的簡(jiǎn)易版。因?yàn)锳TL CString依賴(lài)于MFC頭文件,所以,如果在使用CSTRING而又不想加入過(guò)多其它文件時(shí),WTL CSTRING提供了一個(gè)很好的選擇。
所有文件都分析后,我們發(fā)現(xiàn),atl、mfc、wtl分別定義了一個(gè)CString。其中atl和mfc中的CString都是基于CStringT,只有一個(gè)地方是不同的,即CStringT所引用的StringTrait(即StrTraitsATL 還是 StrTraitMFC)。而WTL CString 的實(shí)現(xiàn)是獨(dú)立的,是一個(gè)真正的類(lèi)。另外 ,StringTrait引用的Iterator是可選的(即底層字符串操作封裝)。
***,我們發(fā)現(xiàn)ATL和MFC中涉及CString的類(lèi)關(guān)系有些復(fù)雜。
為什么ATL和MFC的CString頭文件要攪在一起?
上文的分析有些雜亂,我們通過(guò)一張圖來(lái)更加清晰的觀(guān)察,如下:
上圖中,用圈圈住的頭文件表示ATL頭文件,沒(méi)被圈的代表MFC頭文件。另外,在頭文件旁邊字符,表示各個(gè)頭文件中實(shí)現(xiàn)的類(lèi)。
現(xiàn)在讓我們仔細(xì)觀(guān)看,整個(gè)貌似平衡的設(shè)計(jì)中,其實(shí)有著很多的不平衡。我想問(wèn):
1、為什么MFC頭文件cstringt.h要包含atl頭文件atlsimpstr.h?為什么ATL頭文件要包含cstringt.h?ATL搞ATL的,MFC搞MFC的,各不相干,起不更好?
2、ChTraitOS 放在 atlstr.h 中,而 ChTraitCRT 放在 cstringt.h中,他倆功能是類(lèi)似的,邏輯上是相對(duì)的,為神馬在文件層次上卻不對(duì)齊,要如此的別扭?
話(huà)說(shuō)中國(guó)人看待問(wèn)題的時(shí)候,往往把某一大類(lèi)看作一蹴而就的***的整體。譬如Tencent很賺錢(qián),很大,產(chǎn)品推出快,人們就認(rèn)為T(mén)encent內(nèi)部有著良好的組織架構(gòu)。這里我要告訴大家的是,任何大規(guī)模的東西,都是一點(diǎn)一滴積累起來(lái)的。ATL也是,MFC也是。這兩個(gè)東西不是一個(gè)月、兩個(gè)月的開(kāi)發(fā)就成了現(xiàn)在的樣子的,他們都是逐步疊加,逐步改進(jìn)才成了今天這個(gè)強(qiáng)大的庫(kù)的。扯了這些,是要告訴大家,要以變化、積累、動(dòng)態(tài)來(lái)看待和分析事物的衍生。
好了,現(xiàn)在我們來(lái)看為什么微軟會(huì)搞出這么別扭的結(jié)構(gòu)。
話(huà)說(shuō),某一天ATL開(kāi)發(fā)小組發(fā)現(xiàn)老是操作char,太低效,STL的string也不是很好用,于是乎,他們做了一個(gè)為ATL服務(wù)的簡(jiǎn)單的字符串類(lèi),名字叫 CSimpleStringT,通過(guò)typedef,定義成了 CSimpleString。
后天某一天,MFC的人也發(fā)現(xiàn)char和string超不好用,他們發(fā)現(xiàn)公司的ATL小組已經(jīng)做了一個(gè)成熟CSimpleString類(lèi),于是MFC小組拿來(lái)直接使用。在使用中,MFC小組的人發(fā)現(xiàn)CSimpleString做的太簡(jiǎn)單了,有很多的功能,它都不提供,另外,類(lèi)函數(shù)設(shè)計(jì)的也不好用。于是MFC小組的成員決定擴(kuò)展CSimpleString,他們將擴(kuò)展的代碼寫(xiě)進(jìn)cstringt.h中,另外抽離出對(duì)外的接口頭文件afxstr.h,將定義放在了這。(到這里,我們發(fā)現(xiàn)了上面提到問(wèn)題的發(fā)生點(diǎn),MFC的頭文件繼承了ATL頭文件)。
又到后來(lái),MFC小組的某個(gè)成員(主程級(jí))轉(zhuǎn)到了ATL小組,來(lái)到ATL小組后,他發(fā)現(xiàn),平日用慣了CString,現(xiàn)在要用CSimpleString真TM憋屈,于是他建議在ATL中自封裝一個(gè)CStrnig。ATL小組發(fā)現(xiàn),繼然MFC的CString已經(jīng)做得這么成熟穩(wěn)定且好用了,自己沒(méi)必要再另起爐灶,另外,他們發(fā)現(xiàn)cstringt.h是獨(dú)立于MFC其它文件的,雖然屬于MFC小組(MFC小組所寫(xiě)),但是引用的卻都是atl的頭文件,因此,引用cstringt.h不會(huì)融入MFC其它旁大的文件,因此可行。所以綜合以上考慮,ATL小組直接繼承于cstringt頭文件,派生了自己的CString,放在了atlstr.h中。(注意,連名字取得都和afxstr.h相對(duì)應(yīng),到這里,我們又看到,ATL頭文件繼承了MFC頭文件)。
就這樣,誕生了兩份CSring。日子很平淡的一天一天過(guò)去,直到有一天,有個(gè)項(xiàng)目要混用ATL和MFC,他們發(fā)現(xiàn),有兩份CString,編譯不過(guò)!因?yàn)锳TL的CString畢竟只是模仿MFC,于是ATL讓路,加上了宏定義 #ifndef _AFX ,意即,在沒(méi)有使用MFC時(shí),ATL才定義CString。
ATL 和 MFC CString的故事講完了,相信大家對(duì)CString相關(guān)文件目前結(jié)構(gòu)的來(lái)龍去脈應(yīng)該很清楚了。但是WTL呢?為什么WTL也要定義一個(gè)CString?話(huà)說(shuō)WTL編寫(xiě)過(guò)程中,WTL組的后生小輩們看了ATL的CString代碼,他們覺(jué)得咋這CString搞得咋這么復(fù)雜呢?看得頭都大了,于是他們?cè)O(shè)計(jì)了一個(gè)四兩撥千斤的CString,不繼承任何東西,不依賴(lài)任何東西,就是一個(gè)簡(jiǎn)簡(jiǎn)單單的類(lèi)。在初期,他們工作得很好,但是到后期,他們發(fā)現(xiàn),如果兩個(gè)人的代碼用的是不同的CString的話(huà),那么將代碼合并的時(shí)候,編譯不過(guò),和之前遇到的問(wèn)題一樣,會(huì)產(chǎn)生兩個(gè)CString,于是WTL不得不加了另外一個(gè)宏 _WTL_NO_CSTRING 來(lái)禁止WTL CString的編譯。
好了,故事全都講完了,ATL、WTL、MFC,結(jié)論是,先有CAtlSimpleString,后有MFC CString,再有ATL CString,***有WTL CString,唉,微軟的人搞這么復(fù)雜干嘛呢……
文章名稱(chēng):剖析ATL與WTL CString的實(shí)現(xiàn)機(jī)制
新聞來(lái)源:http://m.fisionsoft.com.cn/article/ccoeopo.html


咨詢(xún)
建站咨詢(xún)
