问一个COM聚合的问题

ab 2000-08-10 07:09:00
我现正学潘爱民的《COM原理与应用》,到COM聚合有一段看不懂:(Page106)
B聚合了A,在B初始化内部A对象时:
HRESULT CB::Init()
{
1, IUnknown *pUnknownOuter = (IUnknown *)this;
2, HRESULT result = ::CoCreateInstance(CLSID_CompA, pUnknownOuter, CLSCTX_INPROC_SERVER, IID_IUnknown, (void **)&m_pUnknownInner);
3, result = m_pUnknownInner->QueryInterface(IID_ISomeInterface, (void **)&m_pSomeInterface);
4, pUnknownOuter->Release();
5, return S_OK;
}
书上说第3句在请求ISomeInterface时,外部对象的引用计数加1,而不是内部对象。怎么回事?m_pUnknownInner不是指向内部对象么?第4句更是摸不着头脑。求大侠给解释解释。谢谢。我的信箱:WizardLxj@263.net
...全文
211 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
JGTM2000 2000-08-11
  • 打赏
  • 举报
回复
关于第4句的Release()的用法,是因为Inner对象的ISomeInterface指针被Outer对象*内部*使用,而不是由客户QI的,因此当然不应该算做一次整体对象的引用,也就应该内部消化(Release)掉了,不然内部对象由于这次QI将导致不能正确的被外部对象释放,除非它的析构中再Release一次。
JGTM2000 2000-08-11
  • 打赏
  • 举报
回复
怎么会错呢。为什么叫聚集?就是对象对外是一个聚合的整体。因此被聚集的对象(Inner)的IUnknown接口的实现是和普通对象不一样的,在被聚集的情形下它要把引用计数委托给外层对象(Outer),即IUnknownInner->QI的实现将会用IUnknownOuter的AddRef,这就使得对象具有对外的整体性,也是可聚集对象(aggregatable)在实现时的关键所在。读它10遍,必有所悟。
ab 2000-08-11
  • 打赏
  • 举报
回复
啊!又看了看书,明白了一些:问题的关键在内部对象的非委托QI上,它虽然自己返回了要请求的ISomeInterface,却把引用计数的管理交给了委托IUnknown的AddRef(),于是又传给了外部对象,结果内部对象的引用计数没有增加,而外部对象的引用计数却增加了。这样,内部对象的非委托AddRef和非委托Release在聚合的情况下无论如何都不会调用到。内部对象的引用计数在聚合时一直是1。上面说的这些对么?
另外还有一个问题:在用CoCreateInstance创建内部对象时,会执行到内部对象类工厂的CreateInstance函数,我发现这个函数退出时最后一条语句后面会多执行一个QI,2个Add,2个Release,都是非委托的,顺序如下:
CA::非委托AddRef() Ref=2
CA::非委托Release() Ref=1
CA::非委托QI, Ref=1, IUnknown
CA::非委托AddRef() Ref=2
CA::非委托Release() Ref=1
这是不是COM库由于自己的需要增加的?这几条在外部对象工厂的CreateInstance里面也有,只不过调用的是外部对象的QI,Add和Release。而在只有一个对象的非聚合情况下却没有这些多余的语句,是怎么回事?
ab 2000-08-11
  • 打赏
  • 举报
回复
JGTM2000:
1,你说被聚合时,内部对象的引用计数都委托给外部对象,可是第3句里面那个m_pUnknownInner却是内部对象的非委托IUnknown指针啊?
2,再说假如是委托IUnknown指针,当函数调用运行到第3句内部对象的QI时,内部对象发现自己的外部指针不空,又把调用转给外部对象,而外部对象发现要请求的接口ISomeInterface是由内部对象实现的,于是又调用m_pUnknownInner指向的QI。这岂不是死循环?
3,如果说内部对象的引用计数都委托给外部对象,可是内部对象里面还有自己的一套引用计数,好像是跟外部对象的引用计数独立的,是不是这样:外部对象引用计数=内部对象引用计数+没有内部对象时外部对象的引用计数。如果这个猜测正确,书上说的是不是应该改成这样:在请求ISomeInterface接口时,内部对象和外部对象的引用计数同时加一,只不过客户感觉不到内部对象的存在,当然也感觉不到内部对象引用计数的增加。
xubin_sh 2000-08-10
  • 打赏
  • 举报
回复
大概写错了吧!
1、第3句很明显是调用内部对象的QueryInterface,所以应该是内部对象的引用计数加1。
2、m_pUnknowInner从代码和字面上看应该是内部对象
3、第4句应该是"m_pUnknowInner->Release();我分析作者的意图是:因为CoCreateInstance是m_pUnknowInner对象的引用计数是1,通过QueryInterface之后变成2,作者希望通过第4句m_pUnknowInner->Release()使m_pUnknowInner的引用计数变回到1,是使内部对象的引用计数保持1,以后在析构外部对象时,只要调用一次m_pUnknowInner->Release()就可以了
以上只是我个人的推测,具体还是问潘爱民本人吧

3,245

社区成员

发帖
与我相关
我的任务
社区描述
ATL,Active Template Library活动(动态)模板库,是一种微软程序库,支持利用C++语言编写ASP代码以及其它ActiveX程序。
社区管理员
  • ATL/ActiveX/COM社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧