freepeople性欧美熟妇, 色戒完整版无删减158分钟hd, 无码精品国产vα在线观看DVD, 丰满少妇伦精品无码专区在线观看,艾栗栗与纹身男宾馆3p50分钟,国产AV片在线观看,黑人与美女高潮,18岁女RAPPERDISSSUBS,国产手机在机看影片

正文內(nèi)容

六com接口的其他實(shí)現(xiàn)方法(編輯修改稿)

2024-11-04 13:56 本頁面
 

【文章內(nèi)容簡(jiǎn)介】 作為第三個(gè)的內(nèi)嵌的數(shù)據(jù)成員 ) 我們不能讓客戶有所察覺 ,即 “ 透明 ” 地實(shí)現(xiàn)接口 . 因此這里我們把 COM子對(duì)象對(duì) IUnknown定義的函數(shù)的實(shí)現(xiàn)委托給 COM主對(duì)象來完成 . ? 因此有必要在 COM子對(duì)象中訪問 COM主對(duì)象的成員 . 它們的 This內(nèi)聯(lián)函數(shù)就是這個(gè)目的 : inline BoatPlane* BoatPlane::XBoat::This(void) { return (BoatPlane*)((char*)thisoffsetof(BoatPlane,m_xBoat))。} This函數(shù)把 this指針減去類分量在類中的偏移得到父類指針 . HRESULT BoatPlane::XBoat::QueryInterface(REFIID iid,void **ppv) { return This()QueryInterface(iid,ppv)。 } //通過父類指針調(diào)用父類的實(shí)現(xiàn) ULONG BoatPlane::XBoat:: AddRef() {return This()AddRef()。 } //通過父類指針調(diào)用父類的實(shí)現(xiàn) ULONG BoatPlane::XBoat:: Release() {return This()Release()。} //通過父類指針調(diào)用父類的實(shí)現(xiàn) //對(duì)于 XPlane也采用類似的方法 . 基于復(fù)合技術(shù)的 COM對(duì)象的內(nèi)存結(jié)構(gòu) : COM對(duì)象的結(jié)構(gòu)如下圖所示 : COM 子對(duì)象的實(shí)現(xiàn) 22 ? 基于復(fù)合技術(shù)實(shí)現(xiàn) COM接口 名稱沖突消除了 . XBoat COM子對(duì)象 XBoat::QueryInterface XBoat::AddRef XBoat::Release 對(duì)象狀態(tài)數(shù)據(jù) XBoat::Swim XBoat::GetMaxSpeed IBoat XPlane COM子對(duì)象 XPlane::QueryInterface XPlane::AddRef XPlane::Release XPlane::Fly XPlane::GetMaxSpeed IPlane IUnknown BoatPlane的 QueryInterface AddRef Release 等函數(shù) XBoat的 Swim GetMaxSpeed 等函數(shù) XPlane的 Fly GetMaxSpeed 等函數(shù) IVehicle 另一個(gè) COM子對(duì)象的虛表 ,單繼承自其接口 COM子對(duì)象的虛表 ,單繼承自其接口 , 注意非 COM主對(duì)象的虛表 ! 注意是子對(duì)象 ,而非虛表指針 23 4. 針對(duì)接口的引用計(jì)數(shù) ? 需求 ? 使用復(fù)合技術(shù)需要更多的編碼 ,而且 ,復(fù)合技術(shù)產(chǎn)生的代碼的質(zhì)量也可能不如使用多重繼承的方式好 . ? 復(fù)合技術(shù)實(shí)現(xiàn)接口成功地消除了名字沖突 . 復(fù)合技術(shù)之所以能夠做到這一點(diǎn)是因?yàn)樗鼪]有多重繼承所固有的 “ 潛在的缺陷 ” , 如果這個(gè)缺陷會(huì)影響功能的話 . 實(shí)際上 ,利用復(fù)合技術(shù)的這一個(gè)優(yōu)勢(shì) , 我們還能夠?qū)崿F(xiàn) 針對(duì)接口 的引用計(jì)數(shù) . ? 在此之前 ,我們所謂的引用計(jì)數(shù)都是針對(duì)對(duì)象的 . 一個(gè)對(duì)象的所有接口都對(duì)同一個(gè)計(jì)數(shù)變量進(jìn)行操作 .對(duì)象無法區(qū)分是哪個(gè)接口對(duì)其進(jìn)行操作的 .而且 ,實(shí)際上 ,通常我們也不必區(qū)分它 . ? 但是 ,存在這樣的情況 , 我們的 COM對(duì)象越來越復(fù)雜 ,功能越來越多 .(想一想我們的手機(jī) ) COM對(duì)象為實(shí)現(xiàn)不同的接口準(zhǔn)備了完全不同的資源 ,如果暫時(shí)不使用其中的某個(gè)接口的話 ,我們完全可以對(duì)其所需要的資源暫時(shí)不予分配 .(我們打電話的時(shí)候一定要把攝像頭打開嗎 ?).而把分配工作放到必要時(shí)進(jìn)行 ,而且 ,也要及時(shí)地釋放 . 24 ? 仍然考慮水上飛機(jī) ,在 BoatPlane類中我們定義了一個(gè)成員變量 : char * m_pTonsOfMemForBoat。 這個(gè)成員變量只在 在 swim函數(shù)中要使用 .也就是說 ,只有 IBoat指針會(huì)使用它 .而與 IPlane指針無關(guān) . ? 假設(shè) m_pTonsOfMemForBoat需要分配一個(gè)很大的內(nèi)存空間 .我們當(dāng)然希望只在必要的時(shí)候分配 .然而 ,如果使用多重繼承的方式實(shí)現(xiàn) COM接口 ,那么意味者所有的虛表中的 AddRef和 Release項(xiàng)都只指向同一個(gè)實(shí)現(xiàn) .也即我們無法從引用計(jì)數(shù)中區(qū)分出 IBoat接口來 .當(dāng)然 ,對(duì)于分配過程我們還是有點(diǎn)辦法 : HRESULT BoatPlane ::QueryInterface(REFIID iid,void **ppv) { if(iid=IID_Boat) { if(m_pTonsOfMemForBoat==NULL) m_pTonsOfMemForBoat=new char[1024*1024*10]。 //任務(wù)只完成了一半 , 10M的內(nèi)存只在最需要的時(shí)候分配 . *ppv=static_castIBoat*(amp。m_xBoat)。 } else if …… } 但是 ,我們無法知道什么時(shí)候釋放掉 .因?yàn)槲覀儾荒荑b別 IBoat和 IPlane所發(fā)出的 Release調(diào)用 . ? 可見 , 針對(duì)接口的引用計(jì)數(shù)有明確的應(yīng)用需求 . 實(shí)現(xiàn)方法如下 : 25 我們使用復(fù)合技術(shù)來實(shí)現(xiàn)針對(duì)接口的引用計(jì)數(shù) . COM 子對(duì)象 XBoat的引用計(jì)數(shù)不再簡(jiǎn)單地委托給 COM主對(duì)象實(shí)現(xiàn) ? 在上一節(jié)的 BoatPlane定義中增加一個(gè)成員變量 int m_BoatRef。 在BoatPlane的構(gòu)造函數(shù)中被賦值 0. 除了 XBoat的 AddRef和 Release函數(shù)變?yōu)?: ? ULONG BoatPlane::XBoat:: AddRef() { ULONG res=InterLockedIncrement(amp。m_BoatRef)。 if(res==1) { This m_pTonsOfMemForBoat=new char[1024*1024*10]。 // 只在 必須分配內(nèi)存的時(shí)候才分配 . ThisAddRef()。} //只在第一次調(diào)用一次主對(duì)象的 AddRef,在主對(duì)象中備案 . return res。 } 實(shí)現(xiàn)方法 26 ULONG BoatPlane::XBoat:: Release() {ULONG res=InterLockedDecrement(amp。m_BoatRef)。 if(res==0) { delete []This m_pTonsOfMemForBoat 。 // 及時(shí)地釋放內(nèi)存 . IPlane接口并不需要它 . 打電話時(shí)關(guān)掉攝像頭 ! ThisRelease()。} //最后一次調(diào)用一次主對(duì)象的 Release。通知主對(duì)象 , 不必為此子對(duì)象而保持引用了 return res。 } XPlane的引用計(jì)數(shù)函數(shù)保持不變 . 客戶的使用完全與以前一致 . 27 ? 為了使得此技術(shù)能正常工作 ,必須保證所有的接口指針用戶遵從COM規(guī)范的要求 , Release調(diào)用必須作用在它對(duì)應(yīng)的 AddRef指針上 . 即 AddRef和 Release必須完全保持配對(duì) .因此在標(biāo)準(zhǔn)的QueryInterface中 ,在 ppv指針賦值后 ,要使用 ((IUnkown*)(*ppv))AddRef()。 //使用新指針 而不能使用 AddRef()。 //使用舊指針 . ? 新舊指針指向同一個(gè) COM對(duì)象的接口 , 它們有可能指的同一個(gè)對(duì)象 .(在多重繼承的情況下 ,同一個(gè)主對(duì)象 ),也有可能指的不同的對(duì)象(在復(fù)合技術(shù)下 ,不同的子對(duì)象 ). 在前者無論使用誰調(diào)用 AddRef都是一樣的 ,在后者則有可能不同 .為了一致起見 ,應(yīng)遵循 COM規(guī)范 ,使用新指針 . ? 以上方案可以實(shí)現(xiàn)針對(duì)接口的引用計(jì)數(shù) ,從而實(shí)現(xiàn)資源的動(dòng)態(tài)最優(yōu)分配和釋放 . 28 ? 多重繼承雖然存在 “ 潛在的缺陷 ” ,但是 , 如果它正好滿足我們的需求 , 實(shí)際上 ,大多數(shù)時(shí)候是滿足的 ,而且具有編碼簡(jiǎn)單 ,代碼質(zhì)量高等優(yōu)點(diǎn) . 而復(fù)合技術(shù)則能避免可能的名字沖突 , 而且可以實(shí)現(xiàn)對(duì)接口的引用計(jì)數(shù) ,提高程序的運(yùn)行效率 . 我們可以 綜合運(yùn)用 以上兩種方法 , 在一個(gè) COM對(duì)象中 ,以不同的方法實(shí)現(xiàn)不同要求的接口 . ? 仍然考慮水上飛機(jī) , 我們可以這樣來實(shí)現(xiàn)它的接口 : 1. 使用繼承的方式實(shí)現(xiàn) IPlane接口 , 2. 使用復(fù)合的方式實(shí)現(xiàn) IBoat接口 (IBoat不是有特殊的引用計(jì)數(shù)要求嗎 ?). ? COM對(duì)象的定義如下 : 29 class BoatPlane: public IPlane //IPlane接口通過繼承的方式實(shí)現(xiàn) { public:BoatPlane(void): m_Ref(0){} HRESULT _stdcall QueryInterface(REFIID iid,void **ppv)。 ULONG _stdcall AddRef()。 //這三個(gè)函數(shù)通過 IPlane從 IUnknown繼承而來 ULONG _stdcall Release()。 //這里改寫虛函數(shù) ,而不像前一節(jié) ,是單純的函數(shù) HRESULT _stdcall Fly()。 //IPlane的函數(shù) HRESULT _stdcall GetMaxSpeed(long *pV)。//IVehicle的函數(shù) struct XBoat:public IBoat{ inline BoatPlane *This()。 //函數(shù)返回指向父類的指針 HRESULT _stdcall QueryInterface(REFIID iid,void **ppv)。 ULONG _stdcall AddRef()。 ULONG _stdcall Release()。 HRESULT _stdcall Swim()。 HRESULT _stdcall GetMaxSpeed(long *pV)。 //COM子對(duì)象的實(shí)現(xiàn)可以 與主對(duì)象的實(shí)現(xiàn)不一致 . 通過 IBoat接口和 IPlane接口能得到不同的結(jié)果 . } m_xBoat。 //嵌套類數(shù)據(jù)成員 ,COM子對(duì)象 實(shí)現(xiàn)了 IBoat接口 . int m_Ref 。 // 用作主對(duì)象的引用計(jì)數(shù) int m_BoatRef。 //用作 COM子對(duì)象 IBoat接口的引用計(jì)數(shù) char * m_pTonsOfMemForBoat。 … .//其他數(shù)據(jù)成員 . } 主對(duì)象的 QueryInterface函數(shù)如下 : 30 HRESULT BoatPlane::QueryInterface(const IIDamp。 iid, void **ppv) { if ( iid == IID_IUnknown) *ppv=static_castIUnknown*(this) //也可以是 //*ppv=static_castIUnknown*(amp。m_xBoat) 。 else if ( iid == IID_IVehicle) *ppv=static_castIVehicle*(this) //也可以是 // *ppv=static_castIVehicle*(amp。m_xBoat) 。 else if ( iid == IID_IBoat) *ppv=static_castIBoat*(amp。m_xBoat) 。 //把 COM子對(duì)象傳出 else if ( iid == IID_IPlane) *ppv=static_castIPlane*(this)。 //把 COM主對(duì)象傳出 else { *ppv=0。 return E_NOINTERFACE。} ( (IUnknown*)(*ppv))AddRef()。 //增加引用計(jì)數(shù) return S_OK。 } ? IPlane接口調(diào)用 QueryInterface當(dāng)然是上述函數(shù) ,而 IBoat的QueryInterface也應(yīng)該委托給它 . 其他的函數(shù)的實(shí)現(xiàn)方式都與以前一樣 . ? 客戶得到的 IPlane接口是指向 COM主對(duì)象 的 ,客戶得到的 IBoat接口是指向 BoatPlane的成員變量 m_xBoat即 COM子對(duì)象 的 .接口的轉(zhuǎn)換過程請(qǐng)自行分析 . 31 ? 其實(shí) ,我們已經(jīng)看到 ,使用繼承或使用復(fù)合來實(shí)現(xiàn)接口的差別并不大 , 這兩種技術(shù)可以和平共處 . 我們?cè)帽砀耱?qū)動(dòng)的方式實(shí)現(xiàn)了多重繼承方式下的 COM接
點(diǎn)擊復(fù)制文檔內(nèi)容
教學(xué)課件相關(guān)推薦
文庫(kù)吧 www.dybbs8.com
備案圖片鄂ICP備17016276號(hào)-1