다음을 통해 공유


인터페이스에 대한 개체 요청

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

모든 COM 인터페이스는 IUnknown 인터페이스에서 직접 또는 간접적으로 상속해야 합니다. 다음 다이어그램에서는 일반 항목 대화 상자 개체의 상속을 보여 줍니다.

일반 항목 대화 상자 개체에 의해 표시되는 인터페이스를 보여 주는 다이어그램

다이어그램에서 볼 수 있듯이 IFileOpenDialog의 바로 상위의 항목은 IFileDialog 인터페이스이며, IModalWindow를 상속합니다. IFileOpenDialog에서 IModalWindow로 상속 체인을 올라가면 인터페이스는 점점 더 일반화된 창 기능을 정의합니다. 마지막으로 IModalWindow 인터페이스는 IUnknown을 상속합니다. 일반 항목 대화 상자 개체는 별도의 상속 체인에 있는 IFileDialogCustomize도 구현합니다.

이제 IFileOpenDialog 인터페이스에 대한 포인터가 있다고 가정합니다. IFileDialogCustomize 인터페이스에 대한 포인터를 얻으려면 어떻게 해야 하나요?

동일한 개체의 인터페이스에 대한 두 개의 인터페이스 포인터를 보여 주는 다이어그램

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

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

QueryInterface 메서드의 서명은 다음과 같습니다.

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

CoCreateInstance에 대해 이미 알고 있는 정보를 바탕으로 QueryInterface의 작동 방식을 추측할 수 있습니다.

  • riid 매개 변수는 사용자가 요청하는 인터페이스를 식별하는 GUID입니다. 데이터 형식 REFIIDconst 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의 메모리 할당