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

正文內(nèi)容

六com接口的其他實現(xiàn)方法-wenkub

2022-10-10 13:56:37 本頁面
 

【正文】 :public IPlane{ //嵌套類從接口類派生 inline BoatPlane *This()。 //這幾個是繼承自 IUnknown,虛的 . ULONG _stdcall Release()。 //這三個函數(shù)不必是虛函數(shù) ULONG _stdcall Release()。 //IXBoat的方法 : HRESULT GetMaxBoatSpeed(long *pV){ *pV=50。 //并沒有引進新技術(shù) ,但是 ,更加形式化 .便于編程 ,提高效率 . 10 2. 多重繼承下的名字沖突 ? 潛在的缺陷 : 使用多重繼承使用 C++類來實現(xiàn) COM接口 ,是一種非常有效的技術(shù) .編碼量小 ,直觀 .建立 COM規(guī)范所要求的 vptr和 vtbl的工作大多由編譯器完成了 . 使用多重繼承 ,一個虛函數(shù)出現(xiàn)在多個基類中 ,在子類中實現(xiàn)后 ,該子類的屬于多個基類的虛表中的該虛函數(shù)的表項 都指向這個實現(xiàn) . QueryInterface, AddRef, Release就是利用這樣的方法實現(xiàn)的 , 而且工作得很好 . 這個特性對于基類中其他的函數(shù)也是成立的 .但是有的時候 ,這就會成為一種限制 .一種 潛在的缺陷 . ? 設(shè)想一種交通工具水上飛機 ,也可以象船一樣在水中航行 .我們做一個 COM對象 BoatPlane,它使用多重繼承的方式實現(xiàn)了接口 IBoat,和接口 IPlane. 這兩個接口都派生自接口 IVehicle. IVehicle有一個函數(shù) GetMaxSpeed以返回該交通工具的最大速度 .IBoat繼承了此函數(shù) .同樣 IPlane也繼承了此函數(shù) . 注意接口是定義函數(shù)的地方 ,它不能夠?qū)崿F(xiàn)它 ,(IBoat和IPlane是抽象基類 ,GetMaxSpeed是純虛函數(shù) ). 在 COM對象類BoatPlane中對此函數(shù)的實現(xiàn) ,會導(dǎo)致 BoatPlane中的屬于 IBoat和IPlane的 GetMaxSpeed函數(shù)表項都指向該實現(xiàn) .這意味著客戶得到COM對象的接口指針 IBoat和 IPlane時 ,調(diào)用 GetMaxSpeed會得到同樣的結(jié)果 ! ? 多重繼承下的名字沖突 . 潛在的缺陷爆發(fā)了 11 ? 本章中用到的類的繼承層次 IUnknown IVehicle IBoat IPlane ? 使用多重繼承的方式實現(xiàn)接口時的潛在缺陷 ? 一種簡單的解決方案是 : IBoat不從 IVehicle派生 , 把 GetMaxSpeed換成GetMasBoatSpeed, IPlane也不從 IVehicle派生 , 把 GetMaxSpeed換成GetMaxPlaneSpeed. 換個名字而已 .再在 BoatPlane類中對這兩個函數(shù)分別實現(xiàn) , 50KM/H, 800KM/H…… 問題似乎解決 ,但是 , 我們要改變接口的繼承結(jié)構(gòu)嗎 ? 而且 , IBoat類的設(shè)計者十分不情愿把 GetMaxSpeed換成 GetMasBoatSpeed, 因為 “ … Boat…”對其而言是多余的 ,不雅觀的 .同樣 ,IPlane的設(shè)計者也有同感 . 畢竟 , 人類對完美的追求是無止境的 …… IUnknown IVehicle IBoat IPlane BoatPlane 定義 GetMaxSpeed 實現(xiàn) GetMaxSpeed 12 ? 一個別致的方案 : 針對 IBoat,設(shè)計一個 中間類 : struct IXBoat:public IBoat { virtual HRESULT GetMaxBoatSpeed(long *pV)=0。 // ISpellCheck成員函數(shù) private : struct DictWord *m_pData。 應(yīng)用 9 ? 我們可以寫成 : ? class CDictionary : public IDictionary , public ISpellCheck { public : CDictionary()。 private : struct DictWord *m_pData。 // IUnknown 成員函數(shù) (在這里要實現(xiàn) ,所以再次申明 ) virtual ULONG __stdcall AddRef() 。 }\ //實現(xiàn) IUnknown定義的三個函數(shù) 8 ? 現(xiàn)在來看應(yīng)用 . 對于第五章字典對象的例子 : ? class CDictionary : public IDictionary , public ISpellCheck {public : CDictionary()。 \ }\ //InterlockedIncrement能防止多線程同時訪問 STDMETHODIMP_(ULONG) Release(void) \ {ULONG res = InterlockedDecrement(amp。 //構(gòu)造函數(shù)使得其值為 define IMPLEMENT_UNKNOWN(ClassName) \ AUTO_LONG m_cRef。//否則循環(huán)遍歷接口表 . } if (hr != S_OK) *ppv = 0。//加上偏移量 . ((IUnknown*)(*ppv))AddRef()。//直接加上第一項的偏移量 . ((IUnknown*)(*ppv))AddRef()。IID_ItfName, ENTRY_IS_OFFSET, BASE_OFFSET(_InterfaceTableClassName, ItfName) }, //接口表項 ,對于接口 ItfName,使用宏計算 ItfName與子類的偏移 . ? define IMPLEMENTS_INTERFACE_AS(RequestedItfName, BaseClassName) \ { amp。 // finder function long dwData。1 六 . COM接口的其他實現(xiàn)方法 1. 基于表格驅(qū)動的接口查詢 1. 接口查詢的本質(zhì) 2. 宏 3. 應(yīng)用 2. 多重繼承下的名字沖突 1. 潛在的缺陷 2. 臨時的方案 3. 使用復(fù)合技術(shù)(嵌套類)實現(xiàn)接口 1. COM主對象和 COM子對象 2. COM 主對象的實現(xiàn) 3. COM 子對象的實現(xiàn) 4. 基于復(fù)合技術(shù)的 COM對象的內(nèi)存結(jié)構(gòu) 使用前面的方法 ,我們已經(jīng)可以順利地實現(xiàn)接口與對象了 .這些基本的技術(shù)是實現(xiàn) COM的基石 .但是 ,人類對于完美與高效的追求是無止境的 .本章介紹一些更加精細的技術(shù) ,看這些技巧是如何提高 COM的效率 ,如何使得 COM的功能細致入微的 . 4. 針對接口的引用計數(shù) 1. 需求 2. 實現(xiàn)方法 5. 多重繼承與復(fù)合的結(jié)合 6. 復(fù)合技術(shù)的表格驅(qū)動 7. 動態(tài)復(fù)合接口 8. MFC對 COM的支持 2 ? 接口查詢的本質(zhì) ? 前面我們使用繼承的方式實現(xiàn)接口 ,使用多重繼承的方式實現(xiàn)多個接口 . 在這種方式下 ,接口的查詢 QueryInterface函數(shù)的實現(xiàn)非常的直接且直觀 . ? 在多重繼承方式下 ,接口類是基類 , IUnkown接口是最上層的基類 . 對象類是接口類的派生的子類 . 在內(nèi)存中 ,子類比基類 “ 大 ” . 因為子類除了包含基類的成員以外 ,還包含自己的成員 .子類的一個實例中包含有基類的一個 “ subobject”,子對象 . 如果這個基類還有基類 ,這個子對象中還含有一個更上層的子對象 . ? QueryInterface函數(shù)的本質(zhì)是 : 使用 statice_cast操作符在子類的對象中加上基類的 偏移 從而從而得到基類的子對象 .轉(zhuǎn)換到不同的基類時 ,要加上不同的偏移 . ? 所以 QueryInterface實際上是在不同的基類和不同的偏移中工作 . 我們可以把基類和對應(yīng)的偏移量抽象出來 .作成表格 .使得QueryInterface的工作更加形式化 . 最終使得 COM的編碼更加形式化 . (這里的工作為向 MFC過渡而熱身 .我們看到 ,MFC中古怪的代碼也是有其理性的由來的 .? ) 3 宏 ? 為了實現(xiàn)表格驅(qū)動的 QueryInterface, 我們定義這樣的一個結(jié)構(gòu) : ? typedef HRESULT (STDAPICALLTYPE *INTERFACE_FINDER)(void *pThis, DWORD dwData, REFIID riid, void **ppv)。 // finder function所需的參數(shù) .這里指偏移量 . } INTERFACE_ENTRY。IID_RequestedItfName, ENTRY_IS_OFFSET , BASE_OFFSET(_InterfaceTableClassName, BaseClassName)}, //接口表項 ,對于請求的接口 RequestedItfName,計算 BaseClassName與子類的偏移 .即請求 RequestedItfName,返回給 BaseClassName,(往往用于菱形多重繼承的情形 .為了避免歧義 ,請求祖父類接口 ,返回父親類接口 .) define END_INTERFACE_TABLE() \ { 0, 0, 0 } }。 //計數(shù)加 1 return S_OK。 //計數(shù)加 1 hr = S_OK。 //不支持此接口 return hr。\ //引用計數(shù)變量 STDMETHODIMP QueryInterface(REFIID riid, void **ppv) \ { return InterfaceTableQueryInterface(this, GetInterfaceTable(), riid, ppv)。)。 ~CDictionary()。 virtual ULONG __stdcall Release() 。 char *m_DictFilename[128]。 ~CDictionary()。 char *m_DictFilename[128]。 //新增加一個純虛函數(shù) . 此函數(shù)在 COM對象中實現(xiàn) HRESULT GetMaxSpeed(long *pV) { return GetMaxBoatSpeed(pV)。} //IXPlane的方法 : HRESULT GetMaxPlaneSpeed(long *pV) { *pV=800。 //嵌套類從接口類派生 struct XBoat : public IBoat{ inline BoatPlane *This()。 HRESULT _stdcall Swim()。 //函數(shù)返回指向父類的指針 HRESULT _stdcall QueryInterface(REFIID iid,void **ppv)。 HRESULT _stdcall GetMaxSpeed(long *pV)。 //為實現(xiàn) Boat功能而需要的數(shù)據(jù) .見后文 … .//其他數(shù)據(jù)成員 . } BoatPlane的 QueryInterface等函數(shù)如下 : 19 HRESULT BoatPlane::QueryInterface(const IIDamp。m_xBoat) 。m_xPlane) 。 //注意只有在對 IUnknown是單繼承的情況下才能使用 (IUnknown*)進行轉(zhuǎn)換 .否則編譯出錯 .如果使用了多繼承 ,要轉(zhuǎn)換為相應(yīng)的具體的接口 . return S_OK。 if (m_Ref == 0 ) { delete this。} This函數(shù)把 this指針減去類分量在類中的偏移得到父類指針 . HRESULT BoatPlane::XBoat::QueryInterface(REFIID iid,void **ppv) { return This()QueryInterface(iid,ppv)。 這個成員變量只在 在 swim函數(shù)中要使用 .也就是說 ,只有 IBoat指針會使用它 .而與 IPlane指針無關(guān) . ? 假設(shè) m_pTonsOfMemForBoat需要分配一個很大的內(nèi)存空間 .我們當(dāng)然希望只在必要的時候分配 .然而 ,如果使用多重繼承的方式實現(xiàn) COM接口 ,那么意味者所有的虛表中的 AddRef和 Release項都只指向同一個實現(xiàn) .也即我們無法從引用計數(shù)中區(qū)分出 IBoat接口來 .當(dāng)然 ,對于分配過程我們還是有點辦法 : HRESULT BoatPlane ::QueryInterface(REFIID iid,void **ppv)
點擊復(fù)制文檔內(nèi)容
教學(xué)課件相關(guān)推薦
文庫吧 www.dybbs8.com
備案圖片鄂ICP備17016276號-1