摘自 http://blog.csdn.net/liang4/article/details/7530512

1 COM组件实际上是一个C++类,而接口都是纯虚类。组件从接口派生而来。

2 COM组件有三个最基本的接口类,分别是IUnknown、IClassFactory、IDispatch。COM规范规定任何组件、任何接口都必须从IUnknown继承,IUnknown包含三个函数,分别是 QueryInterface、AddRef、Release

3 IClassFactory

IClassFactory的作用是创建COM组件。我们已经知道COM组件实际上就是一个类,那我们平常是怎么实例化一个类对象的?是用 ‘new’命令!很简单吧,COM组件也一样如此。但是谁来new它呢?不可能是客户程序,因为客户程序不可能知道组件的类名字,如果客户知道组件的类名字那组件的可重用性就要打个大大的折扣了,事实上客户程序只不过知道一个代表着组件的128位的数字串而已,这个等会再介绍。所以客户无法自己创建组件,而且考虑一下,如果组件是在远程的机器上,你还能new出一个对象吗?所以创建组件的责任交给了一个单独的对象,这个对象就是类厂。每个组件都必须有一个与之相关的类厂,这个类厂知道怎么样创建组件,当客户请求一个组件对象的实例时,实际上这个请求交给了类厂,由类厂创建组件实例,然后把实例指针交给客户程序。这个过程在跨进程及远程创建组件时特别有用,因为这时就不是一个简单的new操作就可以的了,它必须要经过调度,而这些复杂的操作都交给类厂对象去做了。IClassFactory最重要的一个函数就是CreateInstance,顾名思议就是创建组件实例,一般情况下我们不会直接调用它,API 函数都为我们封装好它了,只有某些特殊情况下才会由我们自己来调用它,这也是VC编写COM组件的好处,使我们有了更多的控制机会,而VB给我们这样的机会则是太少太少了。

4 IUnknown

COM规范规定任何组件、任何接口都必须从IUnknown继承,IUnknown包含三个函数,分别是 QueryInterface、AddRef、Release。这三个函数是无比重要的,而且它们的排列顺序也是不可改变的。 QueryInterface用于查询组件实现的其它接口,说白了也就是看看这个组件的父类中还有哪些接口类,AddRef用于增加引用计数, Release用于减少引用计数。引用计数也是COM中的一个非常重要的概念。大体上简单的说来可以这么理解,COM组件是个DLL,当客户程序要用它时就要把它装到内存里。另一方面,一个组件也不是只给你一个人用的,可能会有很多个程序同时都要用到它。但实际上DLL只装载了一次,即内存中只有一个 COM组件,那COM组件由谁来释放?由客户程序吗?不可能,因为如果你释放了组件,那别人怎么用,所以只能由COM组件自己来负责。所以出现了引用计数的概念,COM维持一个计数,记录当前有多少人在用它,每多一次调用计数就加一,少一个客户用它就减一,当最后一个客户释放它的时侯,COM知道已经没有人用它了,它的使用已经结束了,那它就把它自己给释放了。引用计数是COM编程里非常容易出错的一个地方,但所幸VC的各种各样的类库里已经基本上把 AddRef的调用给隐含了,在我的印象里,我编程的时侯还从来没有调用过AddRef,我们只需在适当的时侯调用Release。至少有两个时侯要记住调用Release,第一个是调用了 QueryInterface以后,第二个是调用了任何得到一个接口的指针的函数以后,记住多查MSDN 以确定某个函数内部是否调用了AddRef,如果是的话那调用Release的责任就要归你了。 IUnknown的这三个函数的实现非常规范但也非常烦琐,容易出错,所幸的事我们可能永远也不需要自己来实现它们。

5 IDispatch

IDispatch叫做调度接口。它的作用何在呢?这个世上除了C++还有很多别的语言,比如VB、 VJ、VBScript、JavaScript等等。可以这么说,如果这世上没有这么多乱七八糟的语言,那就不会有IDispatch。:-) 我们知道COM组件是C++类,是靠虚函数表来调用函数的,对于VC来说毫无问题,这本来就是针对C++而设计的,以前VB不行,现在VB也可以用指针了,也可以通过VTable来调用函数了,VJ也可以,但还是有些语言不行,那就是脚本语言,典型的如 VBScript、JavaScript。不行的原因在于它们并不支持指针,连指针都不能用还怎么用多态性啊,还怎么调这些虚函数啊。唉,没办法,也不能置这些脚本语言于不顾吧,现在网页上用的都是这些脚本语言,而分布式应用也是COM组件的一个主要市场,它不得不被这些脚本语言所调用,既然虚函数表的方式行不通,我们只能另寻他法了。时势造英雄,IDispatch应运而生。:-) 调度接口把每一个函数每一个属性都编上号,客户程序要调用这些函数属性的时侯就把这些编号传给IDispatch接口就行了,IDispatch再根据这些编号调用相应的函数,仅此而已。当然实际的过程远比这复杂,仅给一个编号就能让别人知道怎么调用一个函数那不是天方夜潭吗,你总得让别人知道你要调用的函数要带什么参数,参数类型什么以及返回什么东西吧,而要以一种统一的方式来处理这些问题是件很头疼的事。IDispatch接口的主要函数是 Invoke,客户程序都调用它,然后Invoke再调用相应的函数,如果看一看MS的类库里实现 Invoke的代码就会惊叹它实现的复杂了,因为你必须考虑各种参数类型的情况,所幸我们不需要自己来做这件事,而且可能永远也没这样的机会

COM 基础 之 三大基础接口的更多相关文章

  1. java基础语法(三大基础)

    一.标识符 标识符是用于包名.类名.变量名.方法名.对象名.数组名.集合名等的命名:   规则: (1)可以使用英文字母.阿拉伯数字.下划线_.$符号 (2)不能以数字开头 (3)不能使用Java中的 ...

  2. Java14-java语法基础(十三)接口

    Java14-java语法基础(十三)接口 一.接口 1.接口的作用 Java出于安全性.简化程序结构的考虑,不支持多继承而仅支持单继承.然而实际问题中很多情况下仅仅依靠单继承并不能将复杂的问题描述清 ...

  3. Java基础之抽象类与接口

    Java基础之抽象类与接口 对于面向对象编程来说,抽象是它的一大特征之一.在Java中,可以通过两种形式来体现OOP的抽象:接口和抽象类.这两者有太多相似的地方,又有太多不同的地方.很多人在初学的时候 ...

  4. 简易总结react-hook三大基础

    react-hook的最重要的三大基础 import { useEffect, useState, useContext } from 'react' 1.每一个简单的一句话总结 useEffect ...

  5. VLAN 基础设置及Aceess接口

    实验内容 本实验模拟企业网络场景.公司内网是一一个大的局域网,二层交换机S1放置在一楼,在一楼办公的部门有IT部和人事部;二层交换机S2放置在二楼,在二楼办公的部门有市场部和研发部.由于交换机组成的是 ...

  6. 朱晔的互联网架构实践心得S2E7:漫谈平台架构的工作(基础架构、基础服务、基础平台、基础中间件等等)

    前言 程序开发毕竟还不是搬砖这种无脑体力劳动,需要事先有标准,有架构,有设计,绝对不是新公司今天创立,明天就可以开始编码的.其实很多公司在起步的时候没有财力和资源建设独立的基础架构或平台架构部门,甚至 ...

  7. MYSQL、PHP基础、面向对象基础简单复习总结

    一.MYSQL         1.配置MySql                 第一步安装服务器(apache).                 第二部安装MySql界面程序         2 ...

  8. [.net 面向对象编程基础] (3) 基础中的基础——数据类型

    [.net 面向对象编程基础] (3) 基础中的基础——数据类型 关于数据类型,这是基础中的基础. 基础..基础..基础.基本功必须要扎实. 首先,从使用电脑开始,再到编程,电脑要存储数据,就要按类型 ...

  9. [.net 面向对象编程基础] (19) LINQ基础

    [.net 面向对象编程基础] (19)  LINQ基础 上两节我们介绍了.net的数组.集合和泛型.我们说到,数组是从以前编程语言延伸过来的一种引用类型,采用事先定义长度分配存储区域的方式.而集合是 ...

随机推荐

  1. 前端开发 Vue -0前言

    Vue2.0 新手完全填坑攻略——从环境搭建到发布 Vue2 入门,读这篇就够了 Jinkey原创感谢 showonne.yubang 技术指导Demo 地址:http://demo.jinkey.i ...

  2. 【原创】大叔经验分享(93)centos安装oracle客户端

    1 下载客户端 官方下载地址:https://www.oracle.com/database/technologies/instant-client/linux-x86-64-downloads.ht ...

  3. 通过Nginx统计网站的PV、UV、IP

    转载:通过Nginx统计网站的PV.UV.IP 概念 UV:独立访客:以cookie为依据,假设一台电脑装有3个不同的浏览器,分别打开同一个页面,将会产生3个UV.PV:访问量:页面每访问或刷新一次, ...

  4. c#排序sql语句查询

    排序存储的效果图: 根据id排序的sql存储过程: DECLARE @type varchar() ' ' Order By charindex(','+ convert(varchar,id) +' ...

  5. JsonObject转换失败的bug

    使用过程发现初始化失败,终于找到原因 转换的字符串必须都是字符串,不能没有双引号,否则转换失败

  6. django中解决跨域问题

    -跨域问题 -浏览器的:同源策略,浏览器拒绝不是当前域域返回的数据 -ip地址和端口号都相同才是同一个域 -如何解决: -CORS:跨域资源共享 -简单请求:发一次请求 -非简单请求:非简单请求是发送 ...

  7. 通过字节码分析this关键字以及异常表的重要作用

    在之前的字节码分析中缺少对异常的介绍,这次主要来对字节码异常表相关的东东进行一个学习,下面先来编写一个相关异常的小程序: 接着编译来看用javap -verbose来查看一下它的字节码信息: xion ...

  8. Python基础之异常

    一.摘要 Python使用被称为异常 的特殊对象来管理程序执行期间发生的错误.每当发生让Python不知所措的错误时,它都会创建一个异常对象.如果你编写了处理该异常的代码,程序将继续运行:如果你未对异 ...

  9. tp5 左连接

    db('detainform')->alias('d')->join("information i",'i.z_id=d.z_id','LEFT')->where ...

  10. 通过.frm表结构和.ibd文件恢复数据

    整个恢复过程其实可以总结为下面几步: (1):恢复表结构 (2):复制出来创建表的sql语句 (3):恢复表数据(在恢复表数据的时候,首先需要解除当前创建的表与默认生成的.ibd文件间的关系,接着将要 ...