




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、C+類的動態(tài)組件化技術(shù) 09-12-29 13:44:00 作者:未知 編輯:studa090420論文關(guān)鍵詞:COM組件接口生命周期C+類ATL組件類C+基類ATL模板基類繼承 論文摘要:在組件化編程的時(shí)代,如何復(fù)用歷史累積的大量沒有組件特性的C+類?本文從工程的角度對這一問題進(jìn)行探討,利用現(xiàn)有組件技術(shù),提出了一套將C+類平滑過渡到COM組件的完整解決方案。 1. 問題的提出自從Microsoft公布了C
2、OM(Component Object Model,組件對象模型,簡稱COM)技術(shù)以后,Windows平臺上的開發(fā)模式發(fā)生了巨大的變化,以COM為基礎(chǔ)的一系列組件技術(shù)將Windows編程帶入了組件化時(shí)代,傳統(tǒng)的面向?qū)ο蟮能浖_發(fā)方法已經(jīng)逐漸被面向組件的方法所取代。COM標(biāo)準(zhǔn)建立在二進(jìn)制可執(zhí)行代碼級的基礎(chǔ)上,不論何種工具、語言開發(fā)的組件,只要符合COM規(guī)范,就可復(fù)用于VC、VB、Delphi、BC等各種開發(fā)環(huán)境中。COM的語言無關(guān)性將軟件復(fù)用的層次從源代碼級推進(jìn)到了二進(jìn)制級,復(fù)用更方便,也更安全。然而,COM技術(shù)帶來全新的軟件設(shè)計(jì)和開發(fā)模式的同時(shí),也帶來了新的問題。許多軟件公司在開發(fā)自己的軟件產(chǎn)
3、品過程中,都累積了大量C+類,這些代碼設(shè)計(jì)精良,功能完備,以面向?qū)ο蟮臉?biāo)準(zhǔn)來檢驗(yàn)無可挑剔。然而,這些代碼不支持COM,將無法在COM時(shí)代繼續(xù)被復(fù)用。如果它們在軟件組件化的趨勢中被淘汰,那對軟件公司和開發(fā)人員來說都是極大的損失。COM專家Don Box曾說過,“COM is a super C+”。這給了我們一個(gè)啟示,是否可以實(shí)現(xiàn)一種技術(shù),能夠動態(tài)的為普通C+類加上一層COM的封裝呢?這樣,既可以保持這些代碼自身的完整和特性,使它們能繼續(xù)應(yīng)用于原來的系統(tǒng),也可以在需要作為組件使用的時(shí)候,把它們動態(tài)轉(zhuǎn)變成組件,復(fù)用于新系統(tǒng)。一個(gè)自然而然的想法是,為每一個(gè)C+類開發(fā)一個(gè)只暴露一個(gè)接口的COM組件,將
4、原C+類的每個(gè)public方法都對應(yīng)于該接口的一個(gè)方法,接口方法的實(shí)現(xiàn)可以簡單的調(diào)用相對應(yīng)的C+類方法即可。這樣,程序邏輯由原有的C+類控制,但COM層的封裝則由組件提供?;舅悸啡缦聢D所示: 本文就這一技術(shù)展開討論,最終提供一套由普通C+類平滑過渡到COM組件的完整解決方案。我們選用ATL(Active Template Library,活動模板庫,簡稱ATL)作為COM組件的開發(fā)工具,開發(fā)環(huán)境為Visual Studio 6.0。如沒有特殊說明,下文中的“C+類”指沒有組件特性C+類,“C+對象”指C+類的實(shí)例;“ATL組件類”指用于包裝的ATL類,“ATL對象”指ATL組件類的實(shí)例。2.
5、 用ATL包裝C+類 按上述思路將C+對象動態(tài)組件化后,所得的組件實(shí)際上由兩部分組成:ATL組件對象和綁定的C+對象。兩者的生命周期互相牽制,但要保持一致。生命周期的管理是C+類動態(tài)組件化的首要難點(diǎn)。C+類分為兩種,一種是簡單的C+類,一種是集合型的C+類。集合型的C+對象管理一組C+對象,負(fù)責(zé)其創(chuàng)建和刪除,維護(hù)它們的生命周期。下面,分別就簡單C+類和集合型C+類的組件化技術(shù)進(jìn)行說明,展示解決方案的核心技術(shù)。2.1. 簡單C+類的組件化 為使ATL組件類可以自由調(diào)用C+類的方法,需要:l 為ATL組件類安插一個(gè)指針成員變量,指向C+類l 提供ATL對象和C+對象的綁定機(jī)制我們可以在ATL組件類
6、初始化時(shí)創(chuàng)建一個(gè)C+類,用成員變量m_pCPPObj記錄,在析構(gòu)時(shí)刪除,從而實(shí)現(xiàn)ATL組件類和C+類的天然綁定。但出于靈活性考慮,使得ATL組件對象可以綁定任意C+類的對象,我們?yōu)锳TL組件類添加一個(gè)綁定函數(shù)Link2CPPObj(CImplement* pObj)。在ATL組件類的構(gòu)造函數(shù)內(nèi),創(chuàng)建一個(gè)C+對象,用m_pCPPObj記錄。如果調(diào)用了Link2CPPObj,則將m_pCPPObj指向的對象刪除,改用傳入的C+對象。在ATL組件類的的析構(gòu)函數(shù)內(nèi),刪除其綁定的C+對象。由構(gòu)造函數(shù)和Link2CPPObj函數(shù)的定義可知,m_pCPPObj指針總是有意義的。簡單C+類組件化的思想如下圖所
7、示: 2.2. 集合型C+類的組件化 集合型C+類的情況有所不同。集合型C+類以數(shù)組(array)、列表(list)、映射表(map)的形式管理其它C+對象。集合對象和它管理的元素對象都被包裝成組件后,集合型ATL對象可能調(diào)用一個(gè)“Destroy”方法,期望刪除某一個(gè)元素ATL對象;這一操作的實(shí)質(zhì)卻是,集合型C+對象的“Destroy”方法被調(diào)用,將元素C+對象刪除了,而元素ATL對象卻不知道。這一操作的結(jié)果導(dǎo)致了元素的ATL對象存在,而其綁定的C+對象卻被刪除的情況,兩者的生命周期出現(xiàn)了不一致。為了解決這個(gè)問題,我們需要在C+對象被刪除時(shí),能將ATL對象同時(shí)刪除;而在ATL對象的引用計(jì)數(shù)為0
8、需要?jiǎng)h除自身時(shí),也能把C+對象刪除??尚械慕鉀Q方案是:l 在C+類中保存一個(gè)接口指針,指向綁定在一起的ATL對象;為該接口指針賦值的最佳地點(diǎn)顯然是提供綁定機(jī)制的Link2CPPObj函數(shù)內(nèi)部,為此,還需要給Link2CPPObj添加一個(gè)IUnknown*參數(shù)l 在C+類的析構(gòu)函數(shù)中,判斷該接口指針是否為空,如果不為空,則Release對接口的引用,引發(fā)ATL對象自身的析構(gòu)現(xiàn)在,技術(shù)方案如下圖所示: 2.3. 內(nèi)部創(chuàng)建的組件和外部創(chuàng)建的組件 集合型C+類組件化后仍然是集合型ATL組件,它可以創(chuàng)建、刪除自己管理的組件。這樣,組件的創(chuàng)建就可能有兩種情況:l 由客戶直接創(chuàng)建l 由客戶調(diào)用集合型組件的接
9、口方法間接創(chuàng)建創(chuàng)建方式的不同導(dǎo)致了組件生命周期管理的復(fù)雜性。一般說來,組件的創(chuàng)建者負(fù)責(zé)維護(hù)組件的生命周期。上述兩種情況下,分別由客戶和集合型組件維護(hù)被創(chuàng)建組件的生命周期。然而,另有一種情況是,客戶創(chuàng)建了一個(gè)組件,然后送交一個(gè)集合型組件管理,現(xiàn)在維護(hù)組件生命周期的責(zé)任就由客戶轉(zhuǎn)交給了集合型組件。我們的解決方案必須提供這樣的健壯性和靈活性,以維護(hù)各種情況下組件的生命周期。我們?yōu)锳TL組件類添加一個(gè)BOO成員m_bInnerManage,作為組件的維護(hù)標(biāo)識。內(nèi)部維護(hù)意味著組件的生命周期由其它組件(集合型組件)維護(hù);外部維護(hù)則是由客戶維護(hù)。 缺省情況下,組件是外部創(chuàng)建并維護(hù)的,在組件的構(gòu)造函數(shù)內(nèi)設(shè)置外
10、部維護(hù)標(biāo)識。集合型組件創(chuàng)建元素時(shí),需要為元素分別創(chuàng)建一個(gè)C+對象和一個(gè)ATL對象,然后調(diào)用ATL對象的Link2CPPObj函數(shù)將兩者綁定在一起,在Link2CPPObj函數(shù)內(nèi)修改維護(hù)標(biāo)識。對于第三種情況,可以在外部創(chuàng)建組件由客戶轉(zhuǎn)交給集合型組件時(shí),在集合型組件相應(yīng)方法內(nèi)重新設(shè)置維護(hù)標(biāo)識。2.4. C+基類 為了對現(xiàn)有C+類的改動最小,我們設(shè)計(jì)一個(gè)基類封裝需要為C+類添加的功能。所有需要?jiǎng)討B(tài)組件化的C+類都必須從這個(gè)基類派生,以保證動態(tài)組件化中C+對象與ATL對象生命周期的一致。如下圖示:實(shí)現(xiàn)代碼如下所示:class CCPP2ATLObjBase
11、; CCPP2ATLObjBase ();public: / IUnknown指針,反指向封裝該CPP類的接口 IUnknown* m_pAssociATLUnk;protected: virtual CCPP2ATLObjBase ();CCPP2ATLObjBase:CCPP2ATLObjBase()
12、60; / 將IUnknown指針初始化為0 m_pAssociATLUnk = NULL;CCPP2ATLObjBase:CCPP2ATLObjBase() / CPP類的對象析構(gòu)時(shí),Release對接口的引用 if (m_pAssociATLUnk)
13、; m_pAssociATLUnk->Release();然后,修改現(xiàn)有各個(gè)C+類,使之從CCPP2ATLObjBase派生,如下面代碼片斷所示:class CImplement : public CCPP2ATLObjBase ;必須指出的是,在CCPP2ATLObjBase基類中,我們設(shè)置的m_pAssociATLUnk變量存在和現(xiàn)有C+類成員命名沖突的問題。但是,考慮到原C+類并沒有組件特性,也應(yīng)該不會有“IUnknown”型指針,因此,
14、只要各個(gè)類的變量命名都按照規(guī)范的命名法,出現(xiàn)這種名字沖突的可能性是極小的。2.5. ATL模板基類 通過以上分析,我們發(fā)現(xiàn),所有的ATL組件類都需要實(shí)現(xiàn)一些相同的功能:l 保留一個(gè)指向其綁定C+對象的指針l 提供一個(gè)Link2CPPObj函數(shù)l 在構(gòu)造函數(shù)中創(chuàng)建一個(gè)綁定C+類的對象為了減化編碼,我們定義一個(gè)帶參數(shù)的模板基類,實(shí)現(xiàn)上述公共功能,模板參數(shù)就是綁定的C+類。然后,所有的ATL組件類都從模板基類中派生?,F(xiàn)在的技術(shù)方案如下圖所示:實(shí)現(xiàn)代碼如下所示:template <class T>class CCPP2ATLTemplateBase : protected:
15、160; / C+類指針 T* m_pCPPObj; / 標(biāo)識繼承該模板的ATL對象是否由內(nèi)部維護(hù) BOOL m_bInnerManage;public: &
16、#160; /* 模板的構(gòu)造函數(shù),實(shí)現(xiàn)如下功能: 1、new一個(gè)C+實(shí)現(xiàn)類對象 2、缺省情況下,ATL對象由外部維護(hù),將內(nèi)部維護(hù)標(biāo)識設(shè)為FALSE 3、將C+類中對ATL接口的反指
17、指針設(shè)置為空 */ CAtlCPP2ATLTemplateBase() m_pCPPObj = new T;
18、; m_bInnerManage = FALSE; m_pCPPObj->m_pAssociATLUnk = NULL; /* 析構(gòu)ATL對象時(shí),如果該ATL對
19、象是由外部創(chuàng)建的, 則顯式的刪除C+對象 如果ATL對象由內(nèi)部維護(hù),那么什么事都不用做 */ virtual CAtlCPP2ATLTemplateBase()
20、60; if (!m_bInnerManage) if (m_pCPPObj)
21、160; delete m_pCPPObj; /*
22、60; Link2CPPObj函數(shù),負(fù)責(zé)綁定C+對象和ATL接口 1、刪除構(gòu)造函數(shù)中new的C+對象,而使用外部傳入的C+對象 2、將ATL對象的內(nèi)部維護(hù)標(biāo)識設(shè)為TRUE 3、設(shè)置C+基類中的接口指針成員 4、因?yàn)锳
23、TL接口傳送給外部使用,需要增加引用計(jì)數(shù) */ virtual void Link2CPPObj(T* pObj, IUnknown* pUnk) ASSERT(pObj != NULL);
24、 ASSERT(pUnk != NULL); if (m_pCPPObj) dele
25、te m_pCPPObj; m_pCPPObj = pObj; m_bInnerManage = TRUE; m_pCPPObj-&
26、gt;m_pAssociATLUnk = pUnk; m_pCPPObj->m_pAssociATLUnk->AddRef(); ;然后,每個(gè)ATL類都從該模板類派生,如下代碼片斷所示:class ATL_NO_VTABLE CATLXX : ,
27、160; / 添加ATL模板基類 public CCPP2ATLTemplateBase<CImplementXX> 3. C+參數(shù)類型的自動化包裝 在本文的技術(shù)方案中,C+類的public方法與ATL組件接口中的方法一一對應(yīng);相應(yīng)的,C+類中方法的參數(shù)類型也要轉(zhuǎn)換為COM規(guī)范所允許的數(shù)據(jù)類型。在基于COM的自動化(Automation)技術(shù)中,Microsoft提供了一套自動化兼容的數(shù)據(jù)類型
28、VARIANT,定義如下:typedef struct FARSTRUCT tagVARIANT VARIANT;typedef struct FARSTRUCT tagVARIANT VARIANTARG;typedef struct tagVARIANT VARTYPE
29、 vt; unsigned short wReserved1; unsigned short
30、160; wReserved2; unsigned short wReserved3; union
31、0; Byte bVal;
32、; / VT_UI1. Short
33、iVal; / VT_I2. long
34、; lVal;
35、; / VT_I4. float fltVal;
36、 / VT_R4. double
37、160; dblVal; / VT_R8.
38、60; VARIANT_BOOL boolVal; / VT_BOOL.
39、 SCODE scode;
40、; / VT_ERROR. CY cyVal; &
41、#160; / VT_CY. DATE
42、; date; / VT_DATE.
43、 BSTR bstrVal;
44、0; / VT_BSTR. DECIMAL FAR* pdecVal; &
45、#160; / VT_BYREF|VT_DECIMAL. IUnknown FAR* punkVal;
46、60; / VT_UNKNOWN. IDispatch FAR* pdispVal;
47、 / VT_DISPATCH. SAFEARRAY FAR* parray;
48、0; / VT_ARRAY|*. Byte FAR* pbVal;
49、60; / VT_BYREF|VT_UI1. short
50、160; FAR* piVal; / VT_BYREF|VT_I2. long
51、60; FAR* plVal; / VT_BYREF|VT_I4.
52、60; float FAR* pfltVal; &
53、#160; / VT_BYREF|VT_R4. double FAR* pdblVal;
54、0; / VT_BYREF|VT_R8. VARIANT_BOOL FAR* pboolVal;
55、 / VT_BYREF|VT_BOOL. SCODE FAR* pscode;
56、60; / VT_BYREF|VT_ERROR. CY
57、60; FAR* pcyVal; / VT_BYREF|VT_CY. DATE
58、60; FAR* pdate; / VT_BYREF|VT_DATE. BSTR
59、160; FAR* pbstrVal; / VT_BYREF|VT_BSTR.
60、60; IUnknown FAR* FAR* ppunkVal; / VT_BYREF|VT_UNKNOWN. IDispatch &
61、#160; FAR* FAR* ppdispVal; / VT_BYREF|VT_DISPATCH. SAFEARRAY
62、 FAR* FAR* pparray / VT_ARRAY|*. VARIANT FAR* pvarVal;
63、 / VT_BYREF|VT_VARIANT. void
64、160; FAR* byref; / Generic ByRef. char
65、0; cVal;
66、0; / VT_I1. unsigned short uiVal;
67、60; / VT_UI2. unsigned long ulVal;
68、160; / VT_UI4. int
69、 intVal; / VT_INT.
70、 unsigned int uintVal; / VT_UINT.
71、60; char FAR * pcVal;
72、60; / VT_BYREF|VT_I1. unsigned short FAR * puiVal;
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 高級衛(wèi)生專業(yè)技術(shù)資格-副高級(兒科護(hù)理)真題庫-2
- 湖北省仙桃、天門、潛江市2024-2025學(xué)年高三年級第一次模擬考試(二)物理試題
- 課題申報(bào)書:加快湖北義務(wù)教育均衡發(fā)展和城鄉(xiāng)一體化研究
- 2025屆江蘇省南通市如東高級中學(xué)高三3月起點(diǎn)調(diào)研考試-物理試題
- 課題申報(bào)書:基于大數(shù)據(jù)的基礎(chǔ)教育集團(tuán)化辦學(xué)效能評估與治理路徑研究
- 興義市第八中學(xué)2024-2025學(xué)年高三第二次聯(lián)考物理試卷含解析
- 山西省呂梁交城縣2021-2022學(xué)年八年級上學(xué)期期末考試物理試題【含答案】
- Chymostatin-B-生命科學(xué)試劑-MCE
- 13-TP-prodrug-生命科學(xué)試劑-MCE
- 貧困地區(qū)兒童營養(yǎng)干預(yù)措施試題及答案
- 2025屆黑龍江省大慶市高三下學(xué)期第三次模擬考試歷史試題(含答案)
- 災(zāi)害自救互救與應(yīng)急逃生知識培訓(xùn)
- 養(yǎng)老院火災(zāi)事故防范重點(diǎn)培訓(xùn)課件
- 便秘的評估與護(hù)理
- 人力資源許可證制度(服務(wù)流程、服務(wù)協(xié)議、收費(fèi)標(biāo)準(zhǔn)、信息發(fā)布審查和投訴處理)
- JTG-T-F20-2015公路路面基層施工技術(shù)細(xì)則
- 江蘇省蘇州市2023-2024學(xué)年五年級下學(xué)期期中綜合測試數(shù)學(xué)試卷(蘇教版)
- 2024年4月貴州省高三年級適應(yīng)性考試物理試卷(含答案)
- 商品售后服務(wù)認(rèn)證實(shí)施規(guī)則
- 倒虹吸水力計(jì)算
- 畢業(yè)論文(設(shè)計(jì))花生脫殼機(jī)設(shè)計(jì)研究
評論
0/150
提交評論