Is there any reason against calling AddRef () directly inside the QueryInterface () implementation?

When implementing IUnknown::QueryInterface() in C ++, there are several caveats with pointer manipulations. For example, when a class implements several interfaces (multiple inheritance) explicit upcasts are needed :

 class CMyClass : public IInterface1, public IInterface2 { }; //inside CMyClass::QueryInterface(): if( iid == __uuidof( IUnknown ) ) { *ppv = static_cast<IInterface1*>( this ); // upcast in order to properly adjust the pointer //call Addref(), return S_OK } 

The reason for increasing efficiency is pretty obvious in multiple inheritance scenarios. However, everyone here and there I also see the following:

 static_cast<IUnknown*>( *ppv )->AddRef(); 

instead of just calling AddRef() from within QueryInterface() .

Is there some reason why I should convert the value previously copied to ppv and not just call AddRef() for the current object?

+4
source share
2 answers

AddRef is purely virtual in IUnknown , and none of the other interfaces implements it, so the only implementation in your program is the one you write in CMyClass . This method overrides both IInterface1::AddRef and IInterface2::AddRef . IUnknown does not contain any data elements (for example, a reference counter), so a problem with a diamond does not cause your class to be susceptible to such a problem as different AddRef calls that act on different data in the same class.

Calls to this->AddRef() will be redirected to the same place as static_cast<IUnknown*>(*ppv)->AddRef() . I see no reason for a more detailed style.

+2
source

The reason for the verbose syntax is probably because ppv can return not only this , which is easy to see in the longer if-else-if . Example from Don Box Essential COM:

 STDMETHODIMP Car::IternalQueryInterface(REFIID riid, void **ppv) { if (riid == IID_IUnknown) *ppv = static_cast<IUnknown*>(&m_innerUnknown); else if (riid == IID_IVehicle) *ppv = static_cast<IVehicle*>(this); else if (riid == IID_ICar) *ppv = static_cast<ICar*>(this); else return (*ppv = 0), E_NOINTERFACE; ((IUnknown*)*ppv)->AddRef(); return S_OK; } 
+1
source

Source: https://habr.com/ru/post/1309423/


All Articles