Dr. GUI on Components, COM, and ATL
从VCKBASE网站上下载了这本电子书,今天看完了Dr. GUI论述COM第二部分.我试着把他翻译下来,以作为学习COM知识的点滴.我想学习好COM,这种想法是半年前,直到今天还没有进展,因为没有一个可以记录笔记的地方.终于我找到CSDN BLOG了,我会陆续把我学习过\想过的一些东西记录在案.
第二部分:COM基础
在第一部分,医生谈到为什么像C++这样的语言没有解决允许您编制非二进制组件的问题.那次讨论的要点是C++并没有打算解决这个问题;相反,它使单-执行程序复用源代码更容易.C++把那个目标实现得非常好.但是我们希望能够混合和匹配来自不同卖主的组件,每次一个组件改变时不需要重新编制部分(或 全部)系统.我们列举了一大堆为什么在这种情景下C++不能够运转的原因.
于是什么?您必须抛弃C++?不是—但是你必须使用一种和你习惯的方式有一点差别的方式.那就是接下来我将讨论的—怎样在C++中使用COM.
那是否意味着如果你不是一位C++程序员,你应该停止阅读呢?不是,因为任何你使用的COM-兼容语言(Visual Basic, Visual J++, Delphi, and others) 都将会做到我接下来谈论的内幕.所以如果你继续 ,你将会获得关于那些 ActiveX控件和COM组件如何工作的有价值的见识.
一 什么是COM
Component Object Model (COM) 是一种软件组件相互通讯的一种方式.
It's a binary and network standard that allows any two components to communicate regardless of what machine they're running on (as long as the machines are connected), what operating systems the machines are running (as long as it supports COM), and what language the components are written in. COM further provides location transparency.
二 对象(objects)
COM基于对象(objects)—但那不同于你在C++或Visual Basic中使用的对象[译者注:注意英文和中文的不同,关键地方我将显示原文](顺便一句,一个对象和一个组件多指同一件事.Dr. GUI 在谈到应用程序框架时称"组件",在谈到执行(implementations)时称"对象".)
首先, COM 对象会良好的封装.你不能获得对象内部执行的权力. 你也没法知道对象可能使用的数据结构. 实际上,对象是如此良好的封装以至COM对象通常以盒子表示.
三 接口:与对象通讯
接下来是接口.接近一个COM对象的唯一方法是通过接口.在下图绘制了一个含IFoo 的对象.
一个接口代表两件事情. 第一,它是你能呼叫的让对象做什么事情的一系列函数.在C++中,接口用抽象基类代表.例如 IFoo 接口可能是:
class IFoo {
virtual void Func1(void) = 0;
virtual void Func2(int nCount) = 0;
};
我们将暂时忽略返回值和继承性. . . 但是请注意接口中可以多于一个函数,并且所有的函数都是纯虚函数: 它们不在类IFoo中执行. 这儿我们没有定义行为—我们仅仅定义了接口有哪些函数. (一个真正的对象有执行体,当然,---那是后话.)
第二—非常重要的一点—一个接口是组件和客户端的合同 (contract ). 换句话说,一个接口不仅定义了什么函数是可用的,它还定义了当函数呼叫时对象做什么(does). 这种语意的定义不是按照对象的特定执行,因此C++代码中没法扮演.
四 接口契约:像钻石,永远
在COM中, 一旦你通过传输组件"编制" 一份接口契约, 七月是永恒的—它不能在任何形式下被更改. 你不能添加,不能删除,不能修改.为什么?因为其它的组件依赖于这份契约.如果你改变了契约,你将颠覆程序. 只要你依然遵守那份契约,你可以改进你的内部执行.
如果你忘记了什么?如果你需要作出改变?怎样全世界改进?
答案很简单:你写一份新的契约.标准的OLE接口列表有以下:IClassFactory 和 IClassFactory2, IViewObject 和IViewObject2, 等等. 并且也提供IFoo2.
五 COM对象支持多重接口---它们能执行多重契约
新的接口通常以下列形式出现:
class IFoo2 : public IFoo {
// Inherited Func1, Func2
virtual void Func2Ex(double nCount) = 0;
};