我发现QueryInterface()
一些实现模式如下所示:
// 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; }
感兴趣的线是用// ###
注释标记的线。
在IUnknown
static_cast
-pointer上调用AddRef()
是否真的有必要? 还是只是没用的样板代码?
换句话说,一个简单的AddRef()
调用(即this->AddRef()
)就好了吗? 如果没有,为什么?
当然,你通常只有一个 AddRef()实现,所以你怎么称呼它并不重要。 注意代码使用ppv
的方式是可能的灵感,它是无类型的(void **),所以需要cast。 也许撕掉会让你做不同的事情。
主要原因是拆卸接口指针(例如对于很少使用的接口)和可聚合的对象(mixin的COM等价物,或多或少)。
在这些情况下(当被要求聚合的IID时,是一个撕裂或聚合器), ppv
不是一个接口指针,指向相同的ref计数的C ++对象。 因此,如果您也想支持这些情况,则该代码是必需的。
通过调用this->AddRef
,可能会获得一些简单性或类型安全性,但代价是不支持未由相同C ++对象明确实现的接口。
PS:与大多数书籍和文档所说的相反,在我看来:
这是我的思路:
IUnknown
的可聚合物体方法,因此完全没有这个特殊问题; 返回的接口不需要是实现QueryInterface
的类的基类。