COM是怎样炼成的?——《COM本质论》第一章读书笔记

 

第一章阅读笔记

1,组件化的起源:

源代码级的复用——》多个应用程序运行时多次加载同一个库——》单一工具库占用了大量资源,缺陷被放大、改进升级困难;

2,动态链接

解决问题1的方式:动态链接。采用__dllexport将工具库的成员函数开放,多个应用程序加载同一个库,占用一份空间;

3,统一链接:DEF文件的引入

       由于dll文件是二进制级代码,而C++在二进制级缺乏标准,不同的编译器产生出不同的二进制代码,因此会造成编译器A产生的dll文件无法用于编译器B的链接,如函数名称修饰。解决这个问题采用的方式是使用“模块定义文件DEF”,在编译生成dll时统一使用def文件中声明的函数名,当引用这个库时统一调用def文件中的名字,这样就在链接层次上实现了库的兼容。

       然而C++语言有非常多的其他特征,所有编译器厂商都会选择自己的独特的方式来实现,这样就导致了其他编译器仍然无法使用二进制代码(dll)。组件程序的各个组件很有可能是由多个不同的编译器分别编译的,因此仍然无法通过链接。

       C++缺少二进制标准,导致了开发时难以跨越DLL的边界。也就是说简单的从DLL中引出C++成员函数是无法真正实现组件开发的。

4,封装和版本

       另外一种情况,在应用程序引用库的头文件时,应用程序必须知道对象的数据结构,导致了代码间的耦合关系。这种耦合关系严重影响了库代码的升级更新,不同版本的库对内存的处理不同,容易造成内存泄露或越界访问。解决该问题的一种方法是为不同版本的dll创建不同的名字,如添加版本号码。但这种方式并不完善,多个版本容易造成混淆。

5,“接口”(其实是代理,因为是一一映射)

       基于问题4中提到的难题,可以采用“接口+实现”的方式来对库代码进行拆分,也就是将实现类的对象指针保存在接口类中,这样实现方式修改时,无须变动接口部分。这相当于在客户程序和库代码之间建立了一个防火墙,有点类似于设计模式中的代理模式。但这种方式的缺点在于过于冗杂,简单重复又无用的代码比较多。

6,真正的接口

       为了减轻上述问题,可以采用虚基类的方式,将实现类定义为接口类的继承:

         a. 将实现类的各种成员函数操作抽象为纯虚函数声明在接口类中;

         b. 将实现类的对象创建作为dll的全局函数引出;

         c. 将实现类的对象销毁抽象为纯虚函数声明在接口类中。

       这样就实现了实现类与接口类的完全拆分,客户应用程序只需要调用dll中的对象创建函数即可获取到相应的实现类对象,然后进行各种操作,在最后可以调用销毁函数对相应的对象进行正确的销毁。

7,接口开辟新世界——“运行时多态”

       6中描述的创建方法不单隔离了客户程序和库代码,也支持库的灵活的插拔。由于各种操作、销毁均声明为纯虚函数,因此不同的实现只需要继承虚接口,对上述纯虚函数进行实现即可。当客户程序需要不同的实现时,只需在调用对象创建全局函数时传入一个参数,即可在dll内部返回一个正确的实现对象,从而完成正确的功能。这就是组件层次的“多态”。

8,接口的扩展

       虚基类开辟了新的世界,但它仍不完美,例如它无法支持接口的升级。如果接口进行升级,那么从前的应用程序将无法使用新的dll代码,因为新老对象均继承自接口类,也就是说新的接口函数暴露给了并不支持的老对象,那么在老对象调用这个新函数时就会出现运行时问题。

       解决这个问题的方法有两种:增加接口类继承的层次、增加接口类继承的分支。这两种方法的共同点是将新的接口函数固定在新的实现类中,但不同的是前者增加了纵深继承,后者增加了横向继承。一般而言,横向继承的可扩展性更强,因为冗余较少。

       增加了继承分支之后,在客户端调用新的接口功能函数时,就可以调用动态转换将老对象转换为对应的新对象,如果转换成功则说明支持,不成功则说明不支持,从而避免了错误。

       与问题3中类似,不同的编译器会实现不同的动态转换dymatic_cast方法,因此必须在接口类中声明一个动态转换的虚函数,然后在dll中进行不同的转换。

9,资源管理

       因为不同的继承机制导致了多种不同种类的对象指针的存在,因此在销毁时出现了麻烦,用户必须正确的调用delete方法,否则将会出错。

解决这个问题的方式是将指针的引用计数,只要进行过创建或转化,都将引用计数自增;相反每次销毁一个时将引用计数自减。把引用计数的操作抽象为接口的虚函数后,对指针的管理也被归纳为统一的方法,这使得资源管理更加方便。

 

总结

       这段文字从C++代码复用开始,逐步将这个代码做成可复用的二进制组件。动态链接库的形式——》接口和实现——》抽象基类——》运行时多态——》多重继承——》动态转换——》资源管理。

       总而言之,我们从头设计了COM方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值