您好,欢迎访问三七文档
COM是ComponentObjectModel(组件对象模型),提供了编写组件的标准方法。组件实际上是一些小的二进制可执行程序。什么是COM组件?Answer:COM组件是以WIN32动态链接库(DLL)或可执行文件(EXE)形式发布的可执行代码组成。COM组件是遵循COM规范编写的COM组件是一些小的二进制可执行文件COM组件可以给应用程序、操作系统以及其他组件提供服务自定义的COM组件可以在运行时刻同其他组件连接起来构成某个应用程序COM组件可以动态的插入或卸出应用COM组件必须是动态链接的COM组件必须隐藏(封装)其内部实现细节COM组件必须将其实现的语言隐藏COM组件必须以二进制的形式发布COM组件必须可以在不妨碍已有用户的情况下被升级COM组件可以透明的在网络上被重新分配位置COM组件按照一种标准的方式来宣布它们的存在Question:组件不是……?Answer:COM组件不是一种计算机语言COM组件不是DLL,只是利用DLL来给组件提供动态链接的能力COM组件不是一个API函数集。COM组件不是类OLE又名Active控件。(ObjectLinkingandEmbedding),对象连接与嵌入,简称OLE技术。OLE不仅是桌面应用程序集成,而且还定义和实现了一种允许应用程序作为软件“对象”(数据集合和操作数据的函数)彼此进行“连接”的机制,这种连接机制和协议称为组件对象模型(COM)。最大优点是快速应用程序开发。支持快速组装,如同搭积木一样。组件应该满足的两个条件:1,动态连接。动态链接库英文为DLL,是DynamicLinkLibrary的缩写形式,DLL是一个包含可由多个程序同时使用的代码和数据的库,DLL不是可执行文件。动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数。函数的可执行代码位于一个DLL中,该DLL包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。DLL还有助于共享数据和资源。多个应用程序可同时访问内存中单个DLL副本的内容。DLL是一个包含可由多个程序同时使用的代码和数据的库2隐藏其内部实现细节,即内部实现环节不应反映到接口上。组件不受语言的限制。API(ApplicationProgrammingInterface,应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件的以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。COM库可以保证大多数应用程序的重要操作可以以相同的方式进行。接口:提供两个不同对象之间的连接,避免对象内部受到干扰。对于COM来说,就是包含一个函数指针数组的内存结构。C++中,接口(可通过纯虚函数实现)是被继承的,接口存在的意义也是被继承,和C++中抽象类(含有纯虚拟函数的类称为抽象类,它不能生成对象)的纯虚函数是相同的,不能被实例化。定义接口的关键字是interface继承接口的关键字是implements,相当于继承类的extends纯虚函数是一种特殊的虚函数,它的一般格式如下:class类名{virtual类型函数名(参数表)=0;…};在许多情况下,在基类中不能对虚函数给出有意义的实现,而把它声明为纯虚函数,它的实现留给该基类的派生类去做。这就是纯虚函数的作用此时涉及到类的继承:多重继承:一个类继承直接继承了一个以上的基类。C++中用抽象基类实现COM接口,对于支持多重接口的COM组件,依靠抽象基类的多重继承实现用组建构造的应用程序结构可复性强纯抽象基类是指只包含纯虚函数的类。将接口看成行为更加贴切。即组件的接口和行为是相互适合的。组件多态性:客户可以用相同的方式处理不同的组件。接口越大,功能越多,可复用性越小。在虚函数表中包含指向成员函数的指针。接口的背后:Vtb1指针是抽象基类指针和函数之间的一个级别。给接口的实现提供了极大的灵活性。并且和实例数据一起保存。Vtb1可由同一类不同实例数据共享且互不影响各自数据。接口的真正威力在于继承此接口的类都可以被用户通过同一种方式处理。11.9号图:此图显示CACB分别有不同的实例数据,不同的vtb1,但各自vtb1有相同的结构,故可以用相同的方式进行访问。即Fx1,Fx2在两个tb1中都分别占据第一,第二表项。这种格式是编译器根据抽象基类的定义产生的,在某个类实现基类时,此时它将被强制使用此格式,当接口返回一个指针时,必须保证此指针指向正确结构。QueryInterface用户不知道某个组件是否支持某个接口即对接口的了解十分有限,因此在运行时可以访问组件。用户对组件知道的越少,组件就越可以最大限度的改变。客户同组件交互是通过一个接口实现的,而且通过此接口查询其他接口,这个接口就是IUnkown,其定义包含在win32sdkUNKNWN.h中:在IUnkown中定义了一个QueryInterface函数,通过调用QueryInterface决定组件是否支持某个接口。所有COM接口都需要继承IUnkown。每个接口的tb1中的前三个函数都是QueryInterface,AddRef,Release。因此组件任意一个接口都可用来获取这个组件所支持的其他接口。IUnkown指针的获取:IUnkown*CreateInstance(),CreateInstance函数可以创建一个组件并返回一个IUnkown指针。通过QueryInterface来查询组件是否支持某个特定接口,若支持,则返回一个指向此接口的指针,若不支持则返回错误代码。QueryInterface有两个参数:HRESULT_stdcallQueryInterface(constIID&iid,void**ppv)第一个参数是:所需接口标识符。第二个参数是:QueryInterface存放所请求接口的指针。返回值并不是标识某个结果的句柄,而是具有特定结构的32位值。QueryInterface的使用:当客户有了一个IUnkown指针之后,要想知道是否支持某特定的接口,可将此接口标识符传给QueryInterface函数,如果成功返回,则可以使用它返回的一个指针了。例如:Voidfoo(IUnkown*pI){IX*pIX=NULL;(为安全起见,将pIX指针指向NULL)HRESUIT_hr=pI-QueryInterface(IID_IX,(void**)&pIX);If(SUCCEDED){pIX-Fx();}}QueryInterface的实现:根据某个给定的IID返回相应接口的指针。若组件支持此接口返回S_OK和相应指针,若组件不支持则返回E_NOINTERFACE并将相应指针置为NULL。实例:CA实现组件中的QueryInterface:InterfaceIX:IUnkown{/*…*/};InterfaceIY:IUnkown{/*…*/};ClassCA:publicIX,publicIY{/*…*/}其中,IX,IY是非虚拟继承,如果虚拟继承,会导致产生与COM不兼容的vtb1,这使得vtb1前三个函数不再是IUnkown的三个成员函数。类型转换:会改变this的值。如:将this指针转换成IX指针所指的地址和将this转换成IY指针所指地址是不同的。Static_castIX*(this)!=static_castIY*(this);Static_castvoid*(this)!=static_castIY*(this);一般将指针赋给void之前要转换成适合的类型。当要返回IUnkown指针时,*ppv=Static_castIUnkown*(this)是不明确的。虽然都是继承的IUnkown,但实际上内容是不一样的。
本文标题:COM组件学习笔记
链接地址:https://www.777doc.com/doc-2906792 .html