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

  这两天看了看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源码容易一些。。。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值