다음을 통해 공유


개체에 인터페이스 요청

앞에서 개체가 둘 이상의 인터페이스를 구현할 수 있음을 확인했습니다. Common Item Dialog 개체는 실제 예제입니다. 가장 일반적인 사용을 지원하기 위해 개체는 IFileOpenDialog 인터페이스를 구현합니다. 이 인터페이스는 대화 상자를 표시하고 선택한 파일에 대한 정보를 가져오기 위한 기본 메서드를 정의합니다. 그러나 고급 사용을 위해 개체는 IFileDialogCustomize인터페이스도 구현합니다. 프로그램은 새 UI 컨트롤을 추가하여 이 인터페이스를 사용하여 대화 상자의 모양과 동작을 사용자 지정할 수 있습니다.

모든 COM 인터페이스는 IUnknown 인터페이스에서 직접 또는 간접적으로 상속해야 합니다. 다음 다이어그램에서는 Common Item Dialog 개체의 상속을 보여 줍니다.

공통 항목 대화 상자 개체에서 노출하는 인터페이스를 보여 주는 다이어그램

다이어그램에서 볼 수 있듯이 IFileOpenDialog의 직접적인 상위 인터페이스는 IFileDialog 인터페이스이며, 이 인터페이스는 IModalWindow을 상속받습니다. IFileOpenDialog에서 IModalWindow로 상속 계층 구조를 올라가면, 인터페이스는 점점 더 일반화된 창 기능을 정의합니다. 마지막으로 IModalWindow 인터페이스는 IUnknown상속합니다. 또한 Common Item Dialog 개체는 별도의 상속 체인에 존재하는 IFileDialogCustomize을 구현합니다.

이제 IFileOpenDialog 인터페이스에 대한 포인터가 있다고 가정합니다. IFileDialogCustomize 인터페이스에 대한 포인터를 어떻게 얻을 수 있나요?

동일한 개체다이어그램

IFileDialogCustomize 포인터에 IFileOpenDialog 포인터를 캐스팅하기만 하면 작동하지 않습니다. 언어에 종속된 기능인 RTTI(런타임 형식 정보) 형식이 없으면 상속 계층 구조에서 "교차 캐스팅"하는 신뢰할 수 있는 방법은 없습니다.

COM 방법은 첫 번째 인터페이스를 개체에 대한 도관으로 사용하여 IFileDialogCustomize 포인터를 제공하도록 개체를 요청하는 방법입니다. 이 작업은 첫 번째 인터페이스 포인터에서 IUnknown::QueryInterface 메서드를 호출하여 수행됩니다. QueryInterface C++의 dynamic_cast 키워드의 언어 독립적 버전으로 생각할 수 있습니다.

QueryInterface 메서드에는 다음 서명이 있습니다.

HRESULT QueryInterface(REFIID riid, void **ppvObject);

CoCreateInstance대해 이미 알고 있는 내용에 따라 QueryInterface 작동 방식을 추측할 수 있습니다.

  • riid 매개 변수는 요청하는 인터페이스를 식별하는 GUID입니다. REFIID 데이터 형식은 const GUID&대한 typedef. 개체가 이미 만들어졌기 때문에 CLSID(클래스 식별자)가 필요하지 않습니다. 인터페이스 식별자만 필요합니다.
  • ppvObject 매개 변수는 인터페이스에 대한 포인터를 받습니다. 이 매개 변수의 데이터 형식은 void**. CoCreateInstance 이 데이터 형식을 사용하는 것과 동일한 이유입니다. QueryInterface COM 인터페이스를 쿼리하는 데 사용할 수 있으므로 매개 변수를 강력하게 입력할 수 없습니다.

다음은 QueryInterface 호출하여 IFileDialogCustomize 포인터를 가져오는 방법입니다.

hr = pFileOpen->QueryInterface(IID_IFileDialogCustomize, 
    reinterpret_cast<void**>(&pCustom));
if (SUCCEEDED(hr))
{
    // Use the interface. (Not shown.)
    // ...

    pCustom->Release();
}
else
{
    // Handle the error.
}

언제나처럼 메서드가 실패하는 경우 HRESULT 반환 값을 확인합니다. 메서드가 성공하면 개체수명 관리에 설명된 대로 포인터를 사용하여 완료되면 Release 호출해야 합니다.

다음

COM에서 메모리 할당