以下的代码段阐明了使用嵌套类来实现集合对象接口的范例: // CSomeObject is an aggregatable object that implements // IUnknown and ISomeInterface class CSomeObject : public IUnknown { private: DWORD m_cRef;// Object reference count IUnknown* m_pUnkOuter; //Outer unknown, no AddRef // Nested class to implement the ISomeInterface interface class CImpSomeInterface: public ISomeInterface { friend class CSomeObject ; private: private:DWORD m_cRef; //Interface ref-count, for debugging private:IUnknown*m_pUnkOuter; // Outerunknown, for delegation private:public: private:CImpSomeInterface() { m_cRef = 0; }; private:~ CImpSomeInterface(void) {}; private:// IUnknown members delegate to the outer unknown private:// IUnknown members do not control lifetime of object private:STDMETHODIMP QueryInterface(REFIID riid, void** ppv) private:{ return m_pUnkOuter->QueryInterface(riid,ppv);}; private:STDMETHODIMP_(DWORD) AddRef(void) private:{ return m_pUnkOuter->AddRef(); }; private:STDMETHODIMP_(DWORD) Release(void) private:{ return m_pUnkOuter->Release();}; private:// ISomeInterface members private:STDMETHODIMP SomeMethod(void) private:{ return S_OK; }; private:} ; private:CImpSomeInterface m_ImpSomeInterface ; private:public: private:CSomeObject(IUnknown * pUnkOuter) { m_cRef=0; // No AddRef necessary if non-NULL as we're aggregated. m_pUnkOuter=pUnkOuter; m_ImpSomeInterface.m_pUnkOuter=pUnkOuter; } ; // Static member function for creating new instances (don't use // new directly).Protects against outer objects asking for interfaces // other than IUnknown static HRESULT Create(IUnknown* pUnkOuter, REFIID riid, void **ppv) { CSomeObject* pObj; if (pUnkOuter != NULL && riid != IID_IUnknown) return CLASS_E_NOAGGREGATION; pObj = new CSomeObject(pUnkOuter); if (pObj == NULL) return E_OUTOFMEMORY; // Set up the right unknown for delegation (the non-aggregation case) if (pUnkOuter == NULL) pObj->m_pUnkOuter = (IUnknown*)pObj ; HRESULT hr; if (FAILED(hr = pObj->QueryInterface(riid, (void**)ppv))) delete pObj ; return hr; } // Implicit IUnknown members, non-delegating // Implicit QueryInterface only controls inner object STDMETHODIMP QueryInterface(REFIID riid, void** ppv) { *ppv=NULL; if (riid == IID_IUnknown) *ppv=this; if (riid == IID_ISomeInterface) *ppv=&m_ImpSomeInterface; if (NULL==*ppv) return ResultFromScode(E_NOINTERFACE); ((IUnknown*)*ppv)->AddRef(); return NOERROR; } ; STDMETHODIMP_(DWORD)AddRef(void) { return++m_cRef; }; STDMETHODIMP_(DWORD)Release(void) { if (--m_cRef != 0) return m_cRef; delete this; return 0; }; };
集合对象
当在一个对象上产生另一个集合对象时,必须遵循以下规则:
当创建一个内部对象时,外部对象必须明确的向Iunknown请求。 外部对象必须保护重入时对破坏代码的人工引用的Release实施。 如果外部对象查询任一内部对象接口,它必须调用自己的未知Release。释放此指针时,外部对象紧随内部对象指针调用自己的外部未知AddRef。 // Obtaining inner object interface pointer pUnkInner->QueryInterface(IID_IFoo,&pIFoo); pUnkOuter->Release(); // Releasing inner object interface pointer pUnkOuter->AddRef(); pIFoo->Release(); 外部对象不能盲目地对内部对象的未被识别接口进行查询,除非操作是为外部对象特定目的。
房间线程化模型
房间模型线程化的细节实际上非常简单,但是必须小心地遵循以下规则: 每个对象存在于单线程中(在单独的房间中)。 所有对一对象的调用必须基于自己的线程(在自己的房间中)。直接从别的线程中调用对象是禁止的。试图用空线程方式使用对象的申请,将在操作系统的未来版本中遇上不能正确运行的问题。这条规则的含义就是在房间之间,必须安排对象的所有指针。 为了处理从不同进程或同一进程的不同房间中的调用,在对象中的每一房间/线程必须有一个消息队列。这就意味着线程的工作函数必须有一个GetMessage/DispatchMessage循环。假如在线程之间有别的同步原语用来通信,那么Microsoft Win32的sgWaitForMultipleObjects将被用来等待消息和线程同步事件。 基于DLL或进程内的对象必须在注册表中标记为"房间识别",通过给注册数据库的InprocServer32关键字增添名为"ThreadingModel=Apartment"的变量实现。 房间识别对象应仔细填写DLL表项。对房间识别对象调用CoCreateInstance的每一个房间将从它的线程调用DllGetClassObject。故DllGetClassObject应能多级类对象或单线程安全对象。从任一线程调用CoFreeUnusedLibraries,都通过主房间线程来调用DllCanUnloadNow.。  
说明:本教程来源互联网或网友上传或出版商,仅为学习研究或媒体推广,wanshiok.com不保证资料的完整性。
2/2 首页 上一页 1 2 |