今天开始写一些自己的读书心得,希望能坚持下去。
第一章 COM是更好的C++
为什么说COM是更好的C++。答:因为COM是可重用的组建结构。
C++通过class的方式进行软件重用,以源代码的形式进行分发。这就带来两个问题:
1. 如果很多程序都需要使用这个class的话,每个程序都需要占用相同大小的资源。
2. 一旦这个class需要更新的话,目标程序需要重新编译链接。
如何解决上面的问题?答:把class以动态链接库(DLL)的形式包装起来,使class的所有方法从DLL中引出来。这样一来上面的两个问题都没有了,但又会带来一个新的问题:
l 这个DLL升级的时候,比如新加一个成员变量的话,原来的EXE有可能会崩溃。
如何解决上面的问题?答:把接口和实现分离开来。也就是说,另外定义一个class A,用这个类来创建另外一个类B的实例。这样的话class A只需要保留一个class B的指针变量就可以了。但是这样并不是非常完美:
l 每次class B 需要增加一个成员函数的时候,相应的class A也需要增加相应的接口。
如何解决上面的问题?答:抽象基类作为二进制接口。也就是说,外部程序包含抽象基类的声明,实现类继承这个抽象基类。这样就需要另外定义一个全局函数来创建实现类。这样的话,问题到解决了。
但是还是需要注意另外三个问题:
1. 运行时多态性
2. 对象扩展性
3. 资源管理
我们走到了哪儿?
这一章从一个简单的C++类开始,然后一步步讨论如何把这个类做成可重用的二进制组件。第一步是以动态链接库(DLL)的形式来发布这个类,以便从物理上把这个类的包装与客户的包装脱离开来。然后我们使用接口和实现的概念,把数据类型的实现细节封装到二进制防火墙后面,使得对象的布局接口能够随时间而进化,但无须要求客户重新编译。在使用抽象类作为定义接口的方法之后,这道防火墙便以vptr和vtbl的形式出现了。接下来,我们使用LoadLibrary和GetProcAddress,在运行时动态的选择同一接口的不同实现(呈现了运行时的多态性)。最后,我们使用与RTTI类似的结构,在运行时动态地询问对象,以确定对象实际上是否实现了指定的接口。这种结构使我们能够扩充接口的现有版本,并且也可以从单个对象暴露多个不相关的接口。
简而言之,我们刚刚设计了组建对象模型(COM:Component Object Model)。