实现接口,从IUnknown开始
2012-03-31 09:21
148 查看
实现接口,从IUnknown开始 有必要回想一下IUnknown派生的每一个接口。因为IUnknown包含了两个COM对象的基本特性——引用计数和接口查询。当你编写组件对象类时(coclass),还要写一个满足自己需要的IUnknown实现。以实现IUnknown接口的组件对象类为例——下面这个例子可能是你编写的最简单的一个组件对象类。我们将在一个叫做CUnknownImpl的C++类中实现IUnknown。下面是这个类的声明: class CUnknownImpl : public IUnknown{public: // 构造函数和析构器 CUnknownImpl(); virtual ~CUnknownImpl(); // IUnknown 方法 ULONG AddRef(); ULONG Release)(); HRESULT QueryInterface( REFIID riid, void** ppv );protected: UINT m_uRefCount; // 对象的引用计数}; 构造器和析构器 构造器和析构器管理服务器的引用计数: CUnknownImpl::CUnknownImpl(){ m_uRefCount = 0; g_uDllRefCount++;}CUnknownImpl::~CUnknownImpl(){ g_uDllRefCount--;} 当创建新的COM对象时,构造器被调用,它增加服务器的引用计数以保持这个服务器驻留内存。同时它还将对象的引用计数初始化为零。当这个COM对象被摧毁时,它减少服务器的引用计数。 AddRef()和Release()这两个方法控制COM对象的生命期。AddRef()很简单:ULONG CUnknownImpl::AddRef(){ return ++m_uRefCount;}AddRef()只增加对象的引用计数并返回更新的计数。Release()更简单:ULONG CUnknownImpl::Release(){ULONG uRet = --m_uRefCount; if ( 0 == m_uRefCount ) // 是否释放了最后的引用? delete this; return uRet;} 除了减少对象的引用计数外,如果没有另外的明确引用,Release()将摧毁对象。Release()也返回更新的引用计数。注意Release()的实现假设COM对象在堆中创建。如果你在全局粘上创建某个对象,当对象试图删除自己时就会出问题。 现在应该明白了为什么在客户端应用程序中正确调用AddRef()和 Release()是如此重要!如果在这了做得不对,你使用的对象会被很快摧毁,这样的话在整个服务器中内存会很快溢出导致应用程序下次存取服务器代码时崩溃。 如果你编写多线程应用,可能会想到使用++&替代InterlockedIncrement()和InterlockedDecrement()的线程安全问题。++&——用于单线程服务器很保险,因为即使客户端应用是多线程的并从不同的线程中进行方法调用,COM库都会按顺序进行服务器的方法调用。也就是说,一旦一个方法调用开始,所有其它试图调用方法的线程都将阻塞,直到第一个方法返回。COM库本身确保服务器一次不会被一个以上的线程闯入。
相关文章推荐
- ATL中IUnknown接口的实现(一)
- 【原创】使用vc向导简历的ATL COM简单对象好像没有IUnknown接口的实现?
- 从fragment开始向上查找实现了某个接口的parent Fragment 或者 Activity
- 显式实现的接口成员--从简单开始(三)
- 实现二------------实现Runnbale接口
- 俄罗斯方块的接口实现
- 简单开始,暂停,继续的倒计时实现
- CXF系列(六):CXF实现REST接口开发
- 微信红包高级接口JAVA实现
- c#多态的重要实现-接口
- 初学ICommand接口,UI响应在viewmodel中实现
- Java代码实现接口测试
- OpenJDK源码研究笔记(十):枚举的高级用法,枚举实现接口,竟是别有洞天
- 使用jwt实现restful接口用户验证
- 使用七牛接口实现图片和文件一键上传
- 《模式――工程化实现及扩展》(设计模式C# 版)《连贯接口 Fluent Interface》――“自我检验"参考答案
- Autofac在项目中应用的体会,一个接口多个实现的情况
- ThinkPHP实现支付宝接口功能
- (转)C#开发微信门户及应用(1)--开始使用微信接口
- 实现HTTP协议Get、Post和文件上传功能——使用libcurl接口实现