在《COM本质论》第162页下面在讲二进制复合时有段话说“如果外部对象可以请求任何类型的初始接口,那么内部对象必须保持两套vptr,一套委托他的QueryInterface、AddRef和Release实现,另一套不委托这些实现。在限制了初始接口是IUnknown后,对象的实现者只需隔离一个vptr作为非委托IUnknown即可。”
这段话是什么意思,怎么理解?能给出个例子吗?不胜感激。
这段话是什么意思,怎么理解?能给出个例子吗?不胜感激。
解决方案 »
- vc程序执行时,指令指针丢失(请vc高手进来讨论)
- 单文档分割视图的显示问题,不同的视图显示不同的图片
- 急求一篇关于移动视音频监控系统的英文文章
- 谁有windows nt filesystem internals 这本书啊
- 高分求高手解决CDWordArray值的传递问题
- Recordset 能不能在Connection关闭的情况下依然处于打开状态?如何做?
- 请问哪里有关于ADO的较为详尽的资料?
- 如何打印FlexGrid
- 继续Win8 64位下HOOK API函数的问题
- winsock问题,各位救命啊!!!
- 为什么在对话框类中定义CComboBox对象后不能响应对话框的DoModal()?
- 打印的问题!!??
另外感谢arxing,虽然你发给我的代码我没看懂。真实抱歉,我对sdk编成只是个七七八八的水平
class Outer:public IOuter{
public:
IUnknown* m_pUnkInner;
Outer(){
m_pUnkInner = CoCreateInstance(CLSID_Inner,this,CLSCTX_ALL,IID_IUnknown,(void**)&m_pUnkInner);
/*
Attention: m_pUnkInner's QI must route the QI request from Outer to Inner::InternalQI
by Inner::InnerIUnknown, otherwise, m_pUnkInner::QI will be routed to Outer::QI,this
will cause a infinite loop
so if you request other interface Instead of IUnkonw at here, Inner must return a pointer
point to a Object who has the ability of route the Inner::QI request Inner::InternalQI
*/
}
QI(REFIID riid,void** ppv){
if(riid == IID_IInner)
/*
Attention: this time m_pUnkInner is point to Inner::m_innerUnknown
so this call is routered to Inner::InternalQI at last
*/
return m_pUnkInner->QI(riid,ppv);
else
...
}
};
class Inner:public Inner{
IUnkown* m_UnkOuter;
QI(REFIID riid,void** ppv){return m_pUnkOuter->QI(riid,ppv);}
AddRef() {m_pUnkOuter->AddRef();}
Release() {m_pUnkOuter->Release();}
InternalAddRef();
InternalRelease();
InternalQI(REDIID riid,void** ppv){
if(riid == IID_UNKNOWN)
*ppv = static_cast<IUnknown*>(&m_innerUnknown);
/*Attention:if QI IID_IUnkown, it return &m_innerUnknown
it means that if you get a IUnknown pointer, it's point to
InnerUnknown and you call QI on it, it will call this method
m_innerUnkown::QI,then Inner::InternalQI();
*/
else if(riid == IID_IInner)
*ppv = static_cast<IInner*>(this);
/*
but if you call QI on this *ppv later, it will call Inner::QI
then Outer::QI.
*/
}
class InnerIUnknown:public IUnknown{
Inner* This(){}
QI(REFIID riid,void** ppv){return This()->InternalQI(riid,ppv);}
AddRef() {This()->InternalAddRef();}
Release() {This()->InternalRelease();}
};
IUnknown m_innerUnknown;
Inner(IUnknown* pUnkOuter){
m_pUnkOuter = pUnkOuter == 0 ? &m_innerUnknown : pUnkOuter;
}
};class InnerObject:public IClassFactory{
STDMETHODIMP CreateInstance(IUnknown* pUnkOuter,REFIID riid,void** ppv){
if(pUnkOuter != 0&& riid != IID_IUnknown) return (*ppv = 0),E_INVALIDARG;
Inner* p = new Inner(pUnkOuter);
p->InternalAddRef();
p->InternalQI(riid,ppv);
p->InternalRelease();
}
};
int main(){
IOuter* pOuter;
IInner* pInner;
CoCreateInstance(CLSID_IOuter,0,CLSCTX_ALL,IID_IUnknown,(void**)&pOuter);
pInner = pOuter->QI(CLSID_IInner,(void**)&pInner);
pOuter = pInner->QI(CLSID_IOuter,(void**)&pOuter);
}
非委托接口指针:内部对象的QI方法调用自己的InternalQI
委托接口指针:内部对象的QI方法委托给外部对象
还要明确两点:
1、外部对象不能在QI时返回内部对象的非委托指针,因为这样最终用户得到的接口只指针的QI方法将无法返回外部对象的接口指针
2、外部对象所包含的内部对象的接口指针必须是非委托接口指针,否则外部对象对内部对象的接口指针的QI方法的调用将造成死循环。
那么,如果外部对象可以用任意内部对象所支持的非委托接口指针作为它所包含的内部对象的代表,则当对外部对象QI与外部对象所保存的内部对象的代表的接口指针的类型一致的接口指针时,将出现矛盾。
1。不明白非委托指针的意思,是只IUnkown指针?还是其他的指针如IX?其他指针并不存在委托与非委托之分。实际上聚合对象的IUnkown实现只是根据OuterUnkown指针是否为NULL来决定是把请求转发到外部对象还是调用非委托IUnkown实现。
2。因为限定第一次请求必须为IUnkown的情况下,除了IUnkown接口的三个函数需要考虑是否聚合的情况外,其他接口不需要考虑聚合,所以不会出现你说的情况,很明显你把所有的接口都理解为有委托与非委托之分了。
各接口之间应该是STR(对称,自反,传递,一个群)。但是inner object的IUnknown却不能有这样的性质。虽然,从它可以query其他的接口,但是其他的接口却无法query到这个non-delegated IUnknown,事实上这个IUnknown既不对称,也不传递。 从外面(client of outer object)看很美,从里面(outer object as a client)看,却不怎么样。我想,inner object由于不符合这个原则,此时不能视为一个完全意义的com object,因而outer object 对它的使用也会有许多不同于未聚合(但不是不可以聚合)的object的特殊要求。与其说这个IUnknown是个接口,不如说它是个句柄,当然是在一定条件下(punkouter!=NULL )。这里我们遇到的实质问题是,无法让两个不同的接口集合通过正常的com查询(queryinterface),得到对方的引用,这是很显然的,因为每一个集合都是自封闭的,如果可以的话,按照STR,那就是一个接口集合。因此即便我们实现两套接口,我们仍要在CoCreateInstance(由outer object 调用)时,明确指定是INondelegatedXXX, 还是 IXXX, 仍然不可能自由,要想得到另一套接口的指针,还要通过其他的途径,比如INondelegetedIf->GetDelegetedIUnknown。所以,从实现上还不如把inner object的IUnknown变成handle实用。