2010-05-11 6 views
4

IUnknown::QueryInterface()을 C++에 구현할 때 포인터 조작이 포함 된 몇 가지주의 사항이 있습니다.QueryInterface() 구현 내에서 AddRef()를 직접 호출하지 않는 이유가 있습니까?

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 
} 

업 캐스팅에 대한 이유는 다중 상속 시나리오에서 매우 분명하다 : 예를 들어, 클래스는 여러 인터페이스 (다중 상속) explicit upcasts are necessary을 구현합니다. 그러나 여기에 모든과가 나는 또한 다음을 참조 :

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

을 대신 단순히 QueryInterface() 구현 내부에서 AddRef()를 호출.

ppv에 이전에 복사 된 값의 캐스트를 현재 개체에서 AddRef() 대신 사용해야하는 이유가 있습니까?

+0

IUnknown 클래스의 정의를 게시 할 수 있습니까? – mukeshkumar

+0

@hype : 예. http://msdn.microsoft.com/en-us/library/ms680509(VS.85).aspx – sharptooth

답변

2

AddRefIUnknown에 순수 가상이며 해당 인터페이스를 구현하지 않으므로 사용자 프로그램의 유일한 구현은 CMyClass에 작성한 것입니다. 그 한 가지 방법은 보다 우선합니다.IInterface1::AddRefIInterface2::AddRef입니다. IUnknown에는 참조 수와 같은 데이터 멤버가 없으므로 다이아몬드 문제로 인해 같은 클래스의 다른 데이터에 대해 AddRef에 대한 다른 호출이 발생하는 등의 문제가 발생하지 않습니다.

this->AddRef()으로의 전화는 static_cast<IUnknown*>(*ppv)->AddRef()과 같은 곳으로 라우팅됩니다. 좀 더 자세한 스타일에 대한 이유는 없습니다.

1

자세한 구문의 이유는 아마도 이 ppv에 반환 될 수 있으며 더 이상 if-else-if에서 간과하기 쉽습니다. Don Box의 필수 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; 
} 
관련 문제