开发者

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

When implementing IUnknown::QueryInterface() in C++ there're several caveats with pointers manipulation. For example, when the class implements several interfaces (multiple inheritance) explicit upcasts are necessary:

class CMyClass : public IInterface1, public IInterface2 { 
}; 

//inside CMyClass::QueryInterface()开发者_StackOverflow社区:
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 upcast is quite clear in multiple inheritance scenarios. However every here and there I also see the following:

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

instead of simply invoking AddRef() from inside QueryInterface() implementation.

Is there any reason I should do the cast of the value previously copied into ppv instead of just calling AddRef() on the current object?


AddRef is pure virtual in IUnknown, and none of the other interfaces implement it, so the only implementation in your program is the one you write in CMyClass. That one method overrides both IInterface1::AddRef and IInterface2::AddRef. IUnknown doesn't have any data members (such as a reference count), so the diamond problem doesn't cause your class to be susceptible to a problem such as different calls to AddRef acting on different data in the same class.

Calls to this->AddRef() are going to be routed to the same place as static_cast<IUnknown*>(*ppv)->AddRef(). I see no reason for the more verbose style.


The reason for the verbose syntax probably lies in the fact that not only this might be returned in ppv, which is easy to overlook in a longer if-else-if. An example from Don Box's 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;
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜