Microsoft DirectX 8.0 (C++)

追加のインターフェイスの要求

通常は、作成メソッドから受け取るインターフェイス ポインタだけで用は足りる。実際、オブジェクトが公開するインターフェイスが IUnknown 以外には 1 つだけであることも少なくない。しかし、多くのオブジェクトは複数のインターフェイスを公開する。このため、複数のインターフェイスへのポインタが必要になる場合もある。作成メソッドによって返されるインターフェイスのほかにもインターフェイスが必要な場合、新しいオブジェクトを作成する必要はない。オブジェクトの IUnknown::QueryInterface メソッドを使って別のインターフェイス ポインタを要求できる。

CoCreateInstance でオブジェクトを作成した場合は、IUnknown インターフェイス ポインタを要求した後、IUnknown::QueryInterface を呼び出すことによって、必要なすべてのインターフェイスを要求できる。ただし、この方法は、必要なインターフェイスが 1 つだけの場合は不便である。また、オブジェクト作成メソッドを使わない場合は、返すインターフェイス ポインタを指定できないので、まったく機能しない。実際には、すべての COM インターフェイスは IUnknown インターフェイスを継承または拡張しているので、通常は、明示的な IUnknown ポインタを取得する必要はない。

インターフェイスの拡張は、C++ のクラスの継承に似ている。子インターフェイスは、親インターフェイスのすべてのメソッドと子独自のメソッドを公開する。実際、「拡張」の代わりに「継承」という表現を使用することも多い。ただし、継承はオブジェクト内部で行われるものである。アプリケーションがオブジェクトのインターフェイスを継承または拡張することはできない。しかし、子インターフェイスを使うと、子と親の両方のインターフェイスのすべてのメソッドを呼び出すことができる。

すべてのインターフェイスは IUnknown の子である。このため、オブジェクトに対して取得してどのインターフェイスを使っても、QueryInterface を呼び出すことができる。QueryInterface を呼び出す場合は、要求するインターフェイスの IID とインターフェイス ポインタのアドレスを指定する必要がある。メソッドから戻るとき、このポインタにインターフェイス ポインタが格納される。たとえば、次のコードは IDirectSound8::CreateSoundBuffer を呼び出してプライマリ サウンド バッファ オブジェクトを作成している。このオブジェクトは、複数のインターフェイスを公開する。CreateSoundBuffer メソッドは IDirectSoundBuffer8 インターフェイスを返す。次のコードでは、IDirectSoundBuffer8 インターフェイスを使って QueryInterface を呼び出すことによって、IDirectSound3DListener8 インターフェイスを要求している。

IDirectSoundBuffer8* pDSBPrimary = NULL;
IDirectSound3DListener8* pDSListener;
...
if(FAILED(hr = g_pDS->CreateSoundBuffer( &dsbd, &pDSBPrimary, NULL )))
  return hr;

if(FAILED(hr = pDSBPrimary->QueryInterface(IID_IDirectSound3DListener8,
                                           (LPVOID *)&pDSListener)))
  return hr;