http://download.csdn.net/source/1687116
1.TearOff接口由来
一般COM组件实现接口支持是通过继承而获取,但是它并不完美。其中一个问题是“vptr-膨胀”(vptr-bloat)。对于一个类继承的每个接口,类的每个实例都有一个vptr。由于某些接口使用的频率很低,所以最好是在使用它们的时候才付出相应的代价。为了实现这里点,Crispin Goswell发明了tear-off接口。
2.ATL对TearOff的内部组件的支持
tear-off接口是按需暴露的接口,但主类并不真正地从它继承。相反而是通过一个辅助类从tear-off接口派生,每当客户请求接口时,再创建这个辅助类的实例。ATL类实现tear-off接口时,使用CComTearOffObjectBase作为它们的基类,而不是CComObjectRootEx,其实CComTearOffObjectBase就是从CComObjectRootEx,派生而来的。
CComTearOffObjectBase 提供了一个额外的服务,缓存tear-off接口的所有者。每个tear-off接口属于一个所有对象,通过m_pOwner变量,使得tear-off实例可以访问所有者的成员数据或者成员函数。
3. 内部组件的IUnknown接口的实现
tear-off派生类不是CComObject,而是CComTearOffObject,CComTearOffObject知道基类的m_pOwner成员,并在构造函数中初始化。为了遵循COM实体身份规则,每个Tear-off都会把新的接口请求转给拥有着。
拥有缓存的tear-off组件的实现
4.ATL对TearOff的外部组件(拥有者组件)的支持
ATL通过下面两个宏实现对tear-off外部组件的支持
通过_Creator或_Cache函数(这两个函数的定义在CComObjectRootBase中)调用CComInternalCreator或CComCreator的CreateInstance函数,创建ATL::CComTearOffObject< x >对象,即tear-off组件对象。
两者的区别是后者能将创建的接口缓存到punk变量中,在组件的生命周期内,下次再使用时tear-off接口不需要再次创建tear-off组件。前者每次使用tear-off接口都需要创建一个tear-off组件实例。
5.tear-off接口实现例子
a.内部组件代码,即tear-off组件代码
组件C代码同B,这里就不再贴了
b.外部组件的代码,即tear-off接口拥有者实现代码
c.测试代码