Reputation: 42984
I found some implementation pattern of QueryInterface()
along these lines:
// Inside some COM object implementation ... virtual HRESULT __stdcall QueryInterface(REFIID riid, void **ppv) { *ppv = /* Find interface ... */ if (*ppv == nullptr) return E_NOINTERFACE; static_cast<IUnknown *>(*ppv)->AddRef(); // ### return S_OK; }
The line of interest is the one marked with the // ###
comment.
Is calling AddRef()
on the IUnknown
static_cast
-pointer really necessary? Or is it just useless boilerplate code?
In other words, would a simple AddRef()
call (i.e. this->AddRef()
) be just fine? If not, why?
Upvotes: 2
Views: 541
Reputation: 8135
The main reasons are tear-off interface pointers (e.g. for rarely used interfaces) and aggregable objects (the COM equivalent of mixins, more or less).
In these cases (a tear-off, or an aggregator when asked for an aggregated IID), the ppv
is not an interface pointer to the same ref-counted C++ object. As such, that code is necessary if you want to support these cases just as well.
By calling this->AddRef
, perhaps you earn a bit of simplicity or type safety, but at the cost of not supporting interfaces not explicitly implemented by the same C++ object.
P.S.: Contrary to what most books and documentation say, in my opinion:
Here's my line of thought:
IUnknown
's methods on aggregable objects, thus not having this particular problem at all;Upvotes: 2
Reputation: 942000
Sure, you normally have only one AddRef() implementation so it doesn't matter how you call it. Note how the way the code uses ppv
was the possible inspiration, it is typeless (void**) so a cast is needed. Maybe a tear-off would make you do this differently.
Upvotes: 2
Reputation: 2145
The interface returned need not be a base class of the class implementing QueryInterface
.
Upvotes: 0