您的位置:首页 > 其它

【原创】使用vc向导简历的ATL COM简单对象好像没有IUnknown接口的实现?

2011-06-17 13:27 411 查看
  这两天看了看COM和ATL,还是有点云里雾里的感觉。对ATL如何实现COM的一个可创建对象还是不太明白,只知道一些概念。知识仅局限于能够使用VC 的向导简历一个ATL工程,增加一个ATL简单对象,然后就看到工程里呼啦啦的多了一堆文件,有IDL,有CPP等等,而且编译能顺利通过,在别的工程里也可以通过CLSID创建这个类的对象,但是看工程里的几个文件,除了在一个头文件中的END_COM_MAP()宏里有IUnknown接口的虚函数声明,我再没有找到IUnknown接口的函数定义。但是后来也没有深究。
    碰巧昨天需要在已经建立好的ATL工程中用到一个IDropTarget接口,用来实现在ActiveX控件上的拖放操作。我第一想到的就是自己从 IDropTarget继承一个类,手动实现IUnknown和IDropTarget的所有方法。这种方法当然是最简单也是最直接的办法。但是我这个工程可是一个ATL工程,有很多ATL的东西已经实现了IUnknown接口,我为什么要自己傻乎乎的再写一遍?于是乎我就开始自己尝试通过继承现有的 ATL实现来避免手工编写IUnknown的接口代码。但是我照着向导实现的类,从CComObjectRootEx和CComCoClass继承后,并没有得到我想要的结果,因为我在这两个基类中没有找到IUnknown的任何实现代码。
   
    今天我新建了一个ATL工程,假设我新建的接口名称为ITest,相应生成的实现类为CTest。我仔细跟踪了一下COM对象创建的过程,通过看源码发现比较重要的几个类的原理:
       CComObjectRootEx:提供了InternalAddRef, InternalRelease和两个资源锁函数Lock和UnLock的实现。
       CComObjectRootBase:这是CComObjectRootEx的基类,它提供了 InternalQueryInterface,OuterQueryInterface, OuterAddRef, OuterRelease等几个重要的函数实现。
       CComCoClass:
            这是一个很重要的类,在这个类里,有两个宏,其中一个是DECLARE_AGGREGATABLE(T),或者是 DECLARE_NOT_AGGREGATABLE等等,这跟创建ATL简单对象时设置的是否可聚合相关。这个宏展开后是这样的:typedef ATL::CComCreator2< ATL::CComCreator< ATL::CComObject< x > >, ATL::CComCreator< ATL::CComAggObject< x > > > _CreatorClass;而CComCoClass提供的CreateInstance函数就是用了_CreatorClass这个定义。通过跟踪 CoCreateInstance调用,可以发现,当我们请求ITest的一个实现时,我们得到的并不是一个CTest实例,而是 CComCoClass::CreateInstance函数调用_CreatorClass::CreateInstance方法,最终调用了new ATL::CComObject<CTest>,由于CComObject<CTest>是从CTest继承过来的,它当然拥有 ITest的接口,我们最终得到的是一个指向ATL::CComObject对象的指针。在CComObject的类定义中,有IUnknown接口三个函数的明确定义,它将AddRef等请求根据是否聚合转发给InternalAddRef或者OuterAddRef.

        看到这里,为了实现一个暴露了IDropTarget接口的类,我想我最好手动写一个类直接从IDropTarget继承比较好,毕竟手动写IUnknown的三个方法要比看ATL源码容易一些。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐