Archived

This topic is now archived and is closed to further replies.

Exellon2000

QueryInterface

Recommended Posts

Okay. I'm haveing a separate class for implementing each of my components like this... I1 -> CImpI1 I2 -> CImpI2 I3 -> CImpI3 . . . In -> CImpIn ... and I want the QueryInterface function for each interface to support all the other interfaces, like a good little component should. Well, I'm not sure if the standard way I do QueryInterface would work right for this:
  
HRESULT CImp_IX :: QueryInterface ( const IID& iid, void** ppv )
{
    if ( iid == IID_IUnknown )
    {
        *ppv = static_cast < IX* > ( this ) ;
    }
    else if ( iid == IID_IX )
    {
        *ppv = static_cast < IX* > ( this ) ;
    }
    else if ( iid == IID_IY )
    {
        *ppv = static_cast < IY* > ( this ) ;
    }
    else if ( iid == IID_IZ )
    {
        *ppv = static_cast < IZ* > ( this ) ;
    }
    else
    {
        *ppv = NULL ;
        return ( E_NOINTERFACE ) ;
    }

    reinterpret_cast < IUnknown* > ( *ppv ) -> AddRef ( VOID ) ;
    return ( S_OK ) ;
}
  
I'm not sure if this would cause errors since the interfaces are in separate classes, or if the classes have anything to do with it whatsoever. Thanks in advance. Edited by - Exellon2000 on January 2, 2002 5:49:26 PM Edited by - Exellon2000 on January 2, 2002 5:50:14 PM Edited by - Exellon2000 on January 2, 2002 8:08:48 PM

Share this post


Link to post
Share on other sites
Hum, I think there will be a problem. You need to make what is call (i think) a Co class than managing the Imp classes.
Like this:

 

class CImpClassX1 : public IX1
{
public:
CImpClassX1( COClassX* pBackObj) //

QueryInterface( ... )
{ return pBackObj->QueryInterface( ... ); } // same for add & release ref

private:
// the others methods


COClassX* pBackObj;
}

class COClassX : public IUnknown
{
public:
COClassX( ): m_ImpIX1( this) // You will have a warning for calling this in the constructor.
// Addref & Release & Query
private:
friend class CImpClassX1;
CImpClassX1 m_ImpIX1;
ULONG m_refCount; // for addref &
}

COClassX::QueryInterface( ... )
{
HRESULT hr = E_NOINTERFACE;
*ppv = NULL;

if (IID_IUnknown == riid){
*ppv = (IUnknown*) this;
}
else if( IID_IX1 == riid ) {
*ppv = (IX1*) &m_ImpIX1;
}
else if( IID_IX2 == riid ) {
*ppv = (IX2*) &m_ImpIX2;
}

if (NULL != *ppv){
((LPUNKNOWN)*ppv)->AddRef();
hr = NOERROR;
}

return (hr);
}


This is A way, many you can do
class COClassX : public IX1, IX2
offenly (just not for aggregation and having 2 function w/ the same prototype).

I have some full source but not really easy, now I prefer using ATL, but doing this in way is needed to understand.

Why English rules?? C pas très malin tout ça!

Edited by - JesterLeCodeur on January 2, 2002 7:47:00 PM

Share this post


Link to post
Share on other sites
Definitely not.

Your QueryInterface() should only return interface pointers for interface IDs that are directly implemented by that class. Your comment "each interface to support all the other interfaces, like a good little component should" only applies when the class implementing the interfaces supports ALL of the interfaces.

You could use multiple inheritance here, so that your impl class inherits from each interface, but be careful, because the compiler can get confused with all the IUnknown''s flying around =).

Another thing is, remember that any code can call QI() on any of those interfaces to get any other interface (provided it knows the IID to query for), so group interfaces logically by functionality, not for your coding convenience.


-Brannon

Share this post


Link to post
Share on other sites