是否有任何理由反对在 QueryInterface() 实现中直接调用 AddRef() ?

发布于 2024-09-01 07:14:50 字数 790 浏览 6 评论 0原文

在 C++ 中实现 IUnknown::QueryInterface() 时,有一些关于指针操作的注意事项。例如,当类实现多个接口(多重继承)显式向上转换是必要的

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 
} 

在多重继承场景中,向上转换的原因非常清楚。然而,我也时不时地看到以下内容:

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

而不是简单地从 QueryInterface() 实现内部调用 AddRef()

我是否应该对之前复制到 ppv 中的值进行转换,而不是仅仅在当前对象上调用 AddRef() ?

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():
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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

守不住的情 2024-09-08 07:14:50

AddRefIUnknown 中是纯虚拟的,其他接口都没有实现它,因此程序中唯一的实现就是您在 CMyClass 中编写的实现>。该方法会覆盖 IInterface1::AddRef 和 IInterface2::AddRef 两者。 IUnknown 没有任何数据成员(例如引用计数),因此菱形问题不会导致您的类容易受到诸如对 AddRef 作用于同一类中的不同数据。

this->AddRef() 的调用将被路由到与 static_cast(*ppv)->AddRef() 相同的位置。我认为没有理由采用更冗长的风格。

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.

旧伤慢歌 2024-09-08 07:14:50

语法冗长的原因可能在于 ppv 中不仅可能返回 this,这在较长的 if-else- 中很容易被忽视 -如果。来自 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;
}

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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文