【问题标题】:Is there any reason against directly calling AddRef() inside QueryInterface() implementation?有什么理由反对在 QueryInterface() 实现中直接调用 AddRef() 吗?
【发布时间】:2011-02-18 03:52:51
【问题描述】:

在 C++ 中实现 IUnknown::QueryInterface() 时,有几个关于指针操作的警告。比如当类实现了多个接口(多重继承)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 
} 

upcast 的原因在多重继承场景中是很清楚的。然而,到处我也看到以下内容:

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

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

有什么理由我应该对先前复制到ppv 的值进行强制转换,而不是仅仅在当前对象上调用AddRef()

【问题讨论】:

标签: c++ visual-c++ com interop com-interop


【解决方案1】:

AddRefIUnknown 中是纯虚的,其他接口都没有实现它,所以你的程序中唯一的实现就是你在CMyClass 中写的那个。那一种方法会覆盖 both IInterface1::AddRefIInterface2::AddRefIUnknown 没有任何数据成员(例如引用计数),因此菱形问题不会导致您的类容易受到问题的影响,例如对 AddRef 的不同调用作用于同一类中的不同数据.

this-&gt;AddRef() 的呼叫将被路由到与static_cast&lt;IUnknown*&gt;(*ppv)-&gt;AddRef() 相同的位置。我认为没有理由使用更冗长的样式。

【讨论】:

    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-06-07
      • 1970-01-01
      • 2019-10-19
      • 2010-09-19
      • 2010-12-17
      • 2016-02-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多