QueryInterface を実装するための規則
COM オブジェクトに対する IUnknown::QueryInterface メソッドの実装を管理する主な規則は 3 つあります。
- オブジェクトには ID が必要です。
- オブジェクト インスタンス上のインターフェイスのセットは静的である必要があります。
- 他のインターフェイスからオブジェクト上の任意のインターフェイスに対してクエリを正常に実行できる必要があります。
オブジェクトに ID が必要
特定のオブジェクト インスタンスに対して、IID_IUnknownを使用して QueryInterfaceを呼び出すと、常に同じ物理ポインター値が返される必要があります。 これにより、任意の 2 つのインターフェイス QueryInterface を呼び出し、結果を比較して、それらがオブジェクトの同じインスタンスを指しているかどうかを判断できます。
オブジェクト インスタンス上のインターフェイスのセットは静的である必要があります
QueryInterface を介してオブジェクトでアクセスできるインターフェイスのセットは、動的ではなく静的である必要があります。 具体的には、QueryInterface が特定の IID のS_OKを 1 回返す場合、同じオブジェクトに対する後続の呼び出しでE_NOINTERFACEを返すことはありません。QueryInterface が特定の IID のE_NOINTERFACEを返す場合、同じオブジェクトに対する同じ IID に対する後続の呼び出しでは、S_OKを返す必要はありません。
他のインターフェイスからオブジェクト上の任意のインターフェイスに対してクエリを正常に実行できる必要があります
つまり、次のコードが考えられます。
IA * pA = (some function returning an IA *);
IB * pB = NULL;
HRESULT hr;
hr = pA->QueryInterface(IID_IB, &pB);
次の規則が適用されます。
オブジェクト上のインターフェイスへのポインターがある場合は、次のような呼び出しで、その同じインターフェイスに対して QueryInterfaceをする必要があります。
pA->QueryInterface(IID_IA, ...)
2 番目のインターフェイス ポインター QueryInterface の呼び出しが成功した場合は、最初のインターフェイスのそのポインターから QueryInterface を する呼び出しも成功する必要があります。 pB が正常に取得された場合は、次も成功する必要があります。
pB->QueryInterface(IID_IA, ...)
どのインターフェイスでも、オブジェクト上の他のインターフェイスに対してクエリを実行できる必要があります。 pB が正常に取得され、そのポインターを使用して 3 番目のインターフェイス (IC) のクエリが正常に実行された場合は、最初のポインター pA を使用して IC のクエリを正常に実行できる必要もあります。 この場合、次のシーケンスが成功する必要があります。
IC * pC = NULL; hr = pB->QueryInterface(IID_IC, &pC); pA->QueryInterface(IID_IC, ...)
インターフェイスの実装では、特定のオブジェクト上のすべてのインターフェイスへの未処理のポインター参照のカウンターを維持する必要があります。 カウンターには、符号なし整数 を使用する必要があります。
リソースが解放されたことをクライアントが認識する必要がある場合は、IUnknown::Releaseを呼び出す前に、上位レベルのセマンティクスを持つオブジェクト上のインターフェイスでメソッド使用する必要があります。
関連トピック
-
IUnknown の使用と実装の