现在的位置: 首页 > 综合 > 正文

Inside COM Object Model

2013年02月16日 ⁄ 综合 ⁄ 共 1280字 ⁄ 字号 评论关闭
前言
C++对象模型经常会受到大家的关注,这个可以从论坛中大量的和C++对象模型有关的帖子就可以看出来,但是我却很少看到讨论COM组件模型的讨论和文章。我现在正在作一些和COM有关的工作,对这个问题也比较感兴趣,我就想自己写一篇关于这个主题的文章。本文的名字是借用一本非常著名的书的名字,那就是<Inside C++ Object Model>。选择这个名字是不是有借助<Inside C++ Object Model>这本书的名气"炒作"自己的嫌疑?呵呵,可能有一点吧。但是这决不是我使用这个名字的真真原因。在通常情况下我们是用C++来编写COM组件,所以我们可以认为COM组件是一种特殊的C++ 对象,如果把所有的C++对象看作是一个集合的话,那COM组件应该是这个集合的一个子集。鉴于COM组件和C++ 对象之间紧密的关系,我选择了这个名字。

预备知识
虽然我们使用任何语言来编写COM组件,只要我们编写的COM组件符合COM规范,但是在大多数情况下我们仍然是采用C++来编写COM组件,而且我们还会使用ATL库来大大简化我们的工作。所以读者在阅读之间,最好有一定的C++/ATL的基础。

COM组件对象
从本质上来说,我们设计COM组件的过程就是设计C++类的过程。相对于普通的C++类,COM组件的设计有一些常见的形式:

  1. COM组件通常采用多继承的方式来设计类。
  2. COM组件的基类通常情况下应该是一些接口类(以"IXXX"形式存在)和一些实现了某些接口的接口实现类 (以"IXXXImpl"形式存在)。从C++实现的角度来看,接口类就是"抽象基类",而接口实现类则是普通的C++类。接口类通常情况下没有数据成员,而接口实现类则允许有数据成员。
  3. COM组件的基类也可以是一些普通的C++类。这种情况并不常见。

无论COM组件在实现的形式上是如何错综复杂,COM组件最重要的工作就是实现接口并向客户端暴露这些接口。接口的实现可以是直接继承自某个接口并在组件中实现,也可以是通过继承某个类来获得对接口的实现。这些对COM组件的模型有什么影响?我们知道,接口实际上就是仅包含一个虚表指针的C++类,这样接口对COM组件的贡献实际上就是物理内存分布中的一个虚表指针。对于普通的接口类(通常以"IXXX"形式存在),它们的虚函数并没有被实现,所以它们的虚表中存放的并不是虚函数的实际地址,在VS编译器存放的是一个由编译器实现的"存根函数"地址,当试图通过虚表找到这个函数并且执行这个函数的时候会抛出异常。对于实现了接口函数的接口实现类(通常以"IXXXImpl"形式存在),它们的虚表中存放的就是虚函数的实际地址。对于COM组件来说,由于它可以拥有多个接口,它可以拥有多个虚表指针,这些虚表指针可以以任意顺序,任意布局分布在COM组件的模型中。当客户程序在COM组件不同接口之间切换时,即客户程序获取COM组件暴露的接口时,实际上客户程序获取的是接口在COM组件中对应的虚表指针。

历史记录
05/12/2007   v1.0
原文的第一版
02/05/2008   v1.1
添加了接口类和接口实现类的虚表内容

抱歉!评论已关闭.