【正文】
return (ULONG) m_Ref。 pIDictionaryForWord AddRef()。 // ... initialize } ULONG CDictionary::AddRef () { m_Ref ++。 virtual ULONG Release() 。 return E_NOINTERFACE 。 IU n k n o w nID ic tio n a ryCD ic tio n a ryIU n k n o w nISp e llCh e c kQueryInterface實(shí)現(xiàn)舉例(續(xù)一) IDictio n a ry 的 v tab le 指針th is 指針I(yè)S p e ll Ch e c k 的 v tab le 指針CDictio n a ry的屬性數(shù)據(jù)Qu e ry In ter f a c eA d d RefRelea se......Qu e ry In ter f a c eA d d RefRelea se......IDictio n a ry成員函數(shù)IS p e ll Ch e c k成員函數(shù)v tab leQueryInterface實(shí)現(xiàn)舉例(續(xù)二) HRESULT CDictionary::QueryInterface(const IIDamp。 ...... QueryInterface實(shí)現(xiàn) ?與對(duì)象的定義有關(guān) ?IUnknown必須是個(gè)靜態(tài)接口指針,其他接口指針可以是動(dòng)態(tài)的 ?QueryInterface在返回接口之前,必須調(diào)用新接口的 AddRef函數(shù) QueryInterface實(shí)現(xiàn)舉例 class CDictionary : public IDictionary , public ISpellCheck { public : CDictionary()。 return。 BO OL In se rtW o rd )( th is * , S tri n g )。 virtual void DeleteWord(String) = 0。 void (*DeleteWord)( IDictionary * this, String)。 COM接口結(jié)構(gòu) 接口指針 指針 指針函數(shù) 1指針函數(shù) 2指針函數(shù) 3。 virtual ULONG __stdcall Release() = 0。 WORD Data2。 if (NULL!=p) { pret= pDynamic_cast(pszinterface)。 if ((p2=(IString2 *)pDynamic_cast(IString2))) { char c = p2FindAt(3)。 else if (strcmp(psz,IPersist)==0) p = static_castIPersist *(this)。 int Length()。 } include class CMyString : public IString2, public IPersist { private: char *m_psz。 virtual void Save(const char *pszFile)=0。 virtual void *Dynamic_cast(const char *psz)=0。 if ((p3=(IPersist *)pDynamic_cast(IPersist))) p3Save(c:\\temp\\)。 else if (strcmp(psz,IPersist)==0) return static_castIPersist *(this)。 } }。 else if (strcmp(psz,IString2)==0) return static_castIString2 *(this)。 ?新對(duì)象實(shí)現(xiàn)兩個(gè)接口: IString2和 IString –不打斷新的客戶與老的對(duì)象之間的關(guān)系 –但是客戶必須明確地知道對(duì)象是否實(shí)現(xiàn)了自己感興趣的接口 對(duì)象實(shí)現(xiàn)多個(gè)接口 ?假如對(duì)象實(shí)現(xiàn)了兩個(gè)接口 IString和 IPersist –客戶需要在 runtime時(shí)明確地知道接口的類(lèi)型信息,包括通過(guò)創(chuàng)建函數(shù)得到的初始接口類(lèi)型 – at runtime, 客戶可以靈活地從一個(gè)接口變換到另一個(gè)接口,如果對(duì)象不支持某個(gè)接口,客戶也有辦法知道 –回憶 RTTI(Runtime type identification) ?dynamic_cast ?RTTI依賴(lài)于編譯器的實(shí)現(xiàn) ?RTTI只能用于類(lèi)的繼承層次中 對(duì)象實(shí)現(xiàn)多個(gè)接口 (續(xù)一 ) ?所以我們需要自己構(gòu)造一套類(lèi)型機(jī)制,要求: –每個(gè)接口都要提供類(lèi)型轉(zhuǎn)換機(jī)制,能轉(zhuǎn)換到同一對(duì)象上實(shí)現(xiàn)的其他接口 –客戶只要得到了一個(gè)接口就可以得到其他的接口,所以創(chuàng)建函數(shù)可以返回任一個(gè)接口 –如果對(duì)象不支持某個(gè)接口,客戶必須能明確地知道,而不是發(fā)生異常 —— robust – Dynamic_cast 對(duì)象實(shí)現(xiàn)多個(gè)接口 (續(xù)二 ) ?一個(gè)對(duì)象實(shí)現(xiàn) IString2和 IString接口 : class IString { virtual void Delete()=0。 virtual char FindAt(int index)。 p = CreateString(Hello)。 public: CMyString(const char * psz)。 if (p) { const char*psz = pFind(llo)。 if (p) { const char*psz = pFind(llo)。 const char*Find(const char *psz)。 純虛基類(lèi)方案 ?前提條件: –在給定平臺(tái)上所有的編譯器都會(huì)產(chǎn)生同樣的二進(jìn)制結(jié)構(gòu) –純虛函數(shù)在單繼承情況下滿足這一條件 ?純虛基類(lèi)只包含虛函數(shù),限定每個(gè)虛函數(shù)的調(diào)用習(xí)慣 ?對(duì)于跨平臺(tái)的情形,我們肯定要通過(guò)中間層,所以暫時(shí)可以不考慮 虛函數(shù)的繼承布局情況 class B : pulic A { private : int value1。 }。 int Length()。 else m_psz[0] = 0。COM接口與對(duì)象 潘愛(ài)民 內(nèi)容 ?組件的接口 ?COM接口 ?COM IDL ?COM對(duì)象 從歷史看 COM ?COM產(chǎn)生的背景 – 93年因?yàn)?OLE 2的需要而產(chǎn)生 – OLE 1的缺陷 ?COM又從 OLE中脫穎而出 – COM的優(yōu)勢(shì)不限于 OLE – COM成為 Microsoft跟上 Inter的一項(xiàng)重要基礎(chǔ)技術(shù) ?今天的 Windows平臺(tái)上, COM無(wú)處不在 COM基礎(chǔ) —— 三個(gè)概念 ?COM組件 –可獨(dú)立發(fā)布的二進(jìn)制組件 –在 Windows平臺(tái)上為 DLL或者 EXE ?COM對(duì)象 –通過(guò) COM接口提供服務(wù) –符合 OO中對(duì)象的基本概念 ?COM接口 –客戶與對(duì)象之間的協(xié)議,對(duì)象實(shí)現(xiàn) COM接口,客戶使用 COM接口 如何設(shè)計(jì)? ?COM組件 –為方便起見(jiàn),只討論 Windows平臺(tái)上DLL類(lèi)型的組件 ?COM對(duì)象 –如何標(biāo)識(shí)一個(gè)對(duì)象?對(duì)象以什么形式存在?客戶如何創(chuàng)建對(duì)象? –對(duì)象如何暴露接口?一個(gè)或是多個(gè)? ?COM接口 –要求:跨編譯器、跨語(yǔ)言、跨平臺(tái) 設(shè)計(jì) COM接口 —— 從 C++入手 ?C++類(lèi):接口與實(shí)現(xiàn)的分離 –接口:類(lèi)的 public部分 class CMyString { private: char *m_psz。 } CMyString::~CMyString() { delete [] m_psz。 }。 class CMyString { private: char *m_psz。 public: virtual void Func1(void) virtual void Func2(void) }。 int Length()。 int n = pLength()。 int n = pLength()。 virtual ~CMyString()。 if (p) { const char*psz = pFind(llo)。 }。 virtual void *Dynamic_cast(const char *psz)=0。 return NULL。 class IPersist { virtual void Delete()=0。 return NULL。 pDelete()。 virtual void DuplicatePointer()=0。 virtual void Load(const char *ps