描述:
一直想好好学这个,可一直学不好,书看了不少,可是总是看到某些部分就很难理解下去。比如“连接点”,线程模式,Marshalling……都是绊脚石,一绊我就过不去。
比如这个问题,大家来解释一下:
A是被B聚合的对象,A对QueryInterface的实现是这样的:
HRESULT CB::QueryInterface(const IID& iid, void **ppv)
{
if ( iid == IID_IUnknown )
{
*ppv = (IUnknown *) this ;
((IUnknown *)(*ppv))->AddRef() ;
} else if ( iid == IID_OtherInterface )
{
*ppv = (IOtherInterface *) this ;
((IOtherInterface *)(*ppv))->AddRef() ;
} else if ( iid == IID_SomeInterface )
{
//m_pUnknownInner指向A
return m_pUnknownInner->QueryInterface(iid, ppv) ;
}
else
{
*ppv = NULL;
return E_NOINTERFACE ;
}
return S_OK;
}
HRESULT CA::QueryInterface(const IID& iid, void **ppv)
{
if ( m_pUnknownOuter != NULL )
//m_pUnknownOuter指向B
return m_pUnknownOuter->QueryInterface(iid, ppv);
else
return NondelegationQueryInterface(iid, ppv);
}
这代码来自潘爱民的书中,我试过了,没有问题,可我不理解。如果客户端已经获取了A的接口,并用这个接口再次请求一个A的接口,m_pUnknownOuter此时指向B,B又会指向A,A又会指向B……那这算不算死循环调用?事实上,这个函数只被调了一次。为什么?
解决方案1:
不用这么细究吧,QueryInterface不就相当于=吗?聚合不就是相当于继承吗?
而且就目前的开发环境下,直接用=就可以了,而且会有意想不到的结果(比如两个接口没任何关系,但有相同的方法或属性,
用=可以通过编译并运行)。关于连结点,找个例子看看就行了。与其深刻钻研atl com原理,不如看几本什么什么实例的书,
这样学起来快,也有信心;学那么深,万一哪天淘汰了不冤吗?
写那本很牛的STL书的人说过了:不要试图超越stl,不要去深究stl怎么实现的,要学使用stl。
借用一下:不要去研究atl什么原理了,不要去钻研atl的内幕了,要学会使用atl就行了。
实际上,作为一个过来人,在真正的com开发过程中,开始的时候,最大麻烦在于什么字符串、数组啊、类型转换啊、界面开发啊这些问题上。
COM方面,最好的书还是Dan Box那本COM本质论
解决方案3: com 当然有法调试,和调试dll差不多 ,在com中设置断点,先启动一个调用这个com的进程,,附加到这个进程当中,然后启动调用com。
你调试一下就知道
虚表改变了不会死循环
有IID的比较的,不会死循环的~