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;
}
};