QueryInterface: オブジェクト内でのナビゲーション

オブジェクト上のインターフェイスへの最初のポインターを取得した後、COM には、オブジェクトが別の特定のインターフェイスをサポートしているかどうかを調べ、サポートしている場合はそのインターフェイスへのポインターを取得する非常に単純なメカニズムがあります。 (オブジェクト上のインターフェイスへの初期ポインターを取得する方法については、オブジェクトへのポインターの取得。)このメカニズムは、IUnknown インターフェイスの QueryInterface メソッドです。 オブジェクトが要求されたインターフェイスをサポートしている場合、メソッドはそのインターフェイスへのポインターを返す必要があります。 これにより、オブジェクトは、オブジェクトがサポートするインターフェイスを自由に移動できます。 QueryInterface では、ネゴシエーションが成功すると、要求「特定のコントラクトをサポートしていますか?」と、そのコントラクトの高パフォーマンスの使用が分離されます。

クライアントが最初にオブジェクトにアクセスすると、そのクライアントは、少なくとも IUnknown インターフェイス ポインター (最も基本的なインターフェイス) を受け取ります。このポインターを使用して、オブジェクトの有効期間を制御できます。このポインターは、オブジェクトの使用が完了したときにオブジェクトに指示し、QueryInterface を呼び出します。 クライアントは、管理している各オブジェクトに対していくつかの操作の実行を要求するようにプログラムされていますが IUnknown インターフェイスにはこれらの操作用の関数がありません。 代わりに、これらの操作は他のインターフェイスを介して表現されます。 したがって、クライアントは、これらのインターフェイスのオブジェクトとネゴシエートするようにプログラムされます。 具体的には、クライアントは QueryInterface を呼び出して、クライアントが目的の操作を呼び出すインターフェイスをオブジェクトに要求します。

オブジェクトは QueryInterface を実装するため、要求を受け入れるか拒否することができます。 オブジェクトがクライアントの要求を受け入れる場合、QueryInterface は要求されたインターフェイスへの新しいポインターをクライアントに返します。 そのインターフェイス ポインターを使用して、クライアントはそのインターフェイスのメソッドにアクセスできます。 一方、オブジェクトがクライアントの要求を拒否した場合、QueryInterface は null ポインター (エラー) を返し、クライアントは目的の関数を呼び出すポインターを持っていません。 この場合、クライアントはその可能性を適切に処理する必要があります。 たとえば、クライアントがオブジェクト上のインターフェイス A へのポインタを持ち、インターフェイス B と C を要求するとします。また、オブジェクトはインターフェイス B をサポートしますが、インターフェイス C はサポートしないとします。その結果、オブジェクトは B へのポインタを返し、C はサポートされていないと報告されます。

重要なポイントは、オブジェクトが QueryInterface の呼び出しを拒否すると、クライアントが要求されたインターフェイスを介して表現された操作を実行するようにオブジェクトに要求できないことです。 クライアントには、そのインターフェイスでメソッドを呼び出すインターフェイス ポインターが必要です。 オブジェクトが要求されたポインタの提供を拒否した場合、クライアントは、そのオブジェクトに対して意図していた操作を何も実行しないか、または別の (おそらくそれほど強力ではない) インターフェイスにフォールバックすることによって、提供しなくても済むように準備しておく必要があります。 COM 機能のこの特徴は、関数を呼び出すまでその関数が機能するかどうかが分からず、さらに失敗の処理が不確実である他のオブジェクト指向システムと比較して、うまく機能します。 QueryInterface は、オブジェクトがメソッドを呼び出す前にインターフェイスをサポートしているかどうかを確認するための、信頼性の高い一貫した方法を提供します。

QueryInterface メソッドは、オブジェクトが特定のコントラクトをサポートしていないことを示す堅牢で信頼性の高い方法も提供します。 つまり、QueryInterface の呼び出しで「古い」オブジェクトに「新しい」インターフェイス (たとえば、古いオブジェクトが出荷された後に発明されたインターフェイス) をサポートするかどうかを尋ねた場合、古いオブジェクトは問題を引き起こすことなく確実にサポートします。クラッシュの場合は、「いいえ」と答えてください。これを支える技術が IID を割り当てるアルゴリズムです。 これは小さな点のように思えるかもしれませんが、システムのアーキテクチャ全体にとって非常に重要であり、新しい機能についてレガシー要素を照会する機能は、驚くべきことに、他のほとんどのオブジェクト アーキテクチャには存在しない機能です。

IUnknown の使用と実装