C++ 通过调用IUnknown::Release()释放COM接口集合

C++ 通过调用IUnknown::Release()释放COM接口集合,c++,com,com-interface,C++,Com,Com Interface,在我的应用程序中,我需要将COM接口的发布推迟到以后。因此,我将接口指针存储在std::vector COMInterfaces中,稍后我将遍历所有指针并调用Release(),如下所示: for(IUnknown* item : COMInterfaces) item->Release(); 然而,在以下第4.1.3节中,我读到: 在COM中,只有接口被引用计数,而不是对象本身。在客户机获得对特定接口的引用后,它必须准确地在该接口上调用release方法,而不是在引用同一对象的不同接口

在我的应用程序中,我需要将COM接口的发布推迟到以后。因此,我将接口指针存储在
std::vector COMInterfaces
中,稍后我将遍历所有指针并调用
Release()
,如下所示:

for(IUnknown* item : COMInterfaces) item->Release();
然而,在以下第4.1.3节中,我读到:

在COM中,只有接口被引用计数,而不是对象本身。在客户机获得对特定接口的引用后,它必须准确地在该接口上调用release方法,而不是在引用同一对象的不同接口上调用release方法

所以,现在我有点困惑,是否可以以多态方式发布接口。我找不到任何文档明确说明这是否正确

编辑: 下面的评论证实了这一点,我将这样使用它。但是,欢迎任何指向官方文档的指针,以及解释为什么有时我会看到以下代码(这也是Microsoft如何定义
SafeRelease()


你不能做的是将IUnknown*投射到其他任何东西中(你必须始终使用QueryInterface,而不是“原始”投射)。如果不这样做,就不会有任何问题。任何COM接口都是IUnknown。只要只调用
AddRef()
Release()
QueryInterface()
,任何向下或向上转换都应该是安全的。假设您有一个
IDispatch
界面。您可以调用
lpDisp->Release()
。如果调用
((IUnknown*)lpDisp)->Release()
,则会得到相同的结果。我相信这一段特别指的是只能通过
查询接口
(而不是向下转换)找到的接口。此时,菱形继承开始发挥作用,每个可查询接口都有自己的
IUnknown
副本。这些副本可以有三种方法的不同实现,这可能是本段警告的。在旁注中,使用
std::vector
会更安全,这样您就不必手动调用
Release()
。这样,当
向量
超出范围时,接口会自动释放,特别是在引发意外异常时。除了
IUnknown*
之外,不能使用任何指针类型调用您的
Release
。这与COM无关,只是基本的类型安全性。如果您可以将
Dervied*p
传递给采用
Base*&
的函数,则该函数可以将一些不相关的
另一个派生的*
分配给
p
template<class T>
void Release(T*& comInterface) {
    if(comInterface) {
      comInterface->Release();
      comInterface = nullptr;
    }
}
void Release(IUnknown*& comInterface) {
    if(comInterface) {
      comInterface->Release();
      comInterface = nullptr;
    }
}