2011-02-03 3 views
2

IUnknown::QueryInterface()を実装する典型的な方法は以下の通りである:多重継承シナリオにおける適切なポインタ調整のためにここでDynamicIncastをQueryInterface実装で使用する必要はありませんか?

if(iid == __uuidof(IInterfaceN)) { 
    *ppv = static_cast<IInterfaceN>(this); 
    //call Addref(), return S_OK 
} 

static_castis necessary次のサポートされている各インタフェースIDにif-else-ifのチェーンを使用して行います。

しばらくして、代わりにdynamic_castを使用する実装があります。 IMOは時間の無駄です - 結果は同じになります、それはちょうど時間がかかり、実装を強調します。

dynamic_castを使用してどのような場合には、IUnknown::QueryInterface()実装のvoid**パラメータにそれをコピーする前にthisポインタをキャストするために実際に必要がありますか?

答えて

1

QueryInterfaceの実装では、「サポートされているインターフェイスID」がわからない場合があります。例えば。 QueryInterfaceをベースクラスに実装し、派生クラスごとにオーバーライドしない場合は、

このような状況が発生するのは、「類似」とは「同じインターフェイスの多くを実装する」という意味の類似したタイプが多い状況です。私。 Derived1 ... ... InterfaceMのサブセットを実装するオブジェクトタイプがDerivedNです。

これは、ゲームエンティティがすべてエトセトラIMoveableIScriptableIFactoryIShootsIPlayerControlledIStealthyISensorのサブセットを実装するゲームエンジンのためのケースである可能性があります。もちろん、COMルールではIFactory::QueryInterfaceに電話してIMovable*を得ることができなければなりません。工場でもIMovableが実装されている場合に限ります。

どのようにこれらのすべての方法を実装するつもりですか? IUnknownIFactoryの間にGameObject基底クラスを挿入するのが最も簡単です。そして、dynamic_castチェックを使用してGameObject::QueryInterfaceを実装します。このようにして、具体的なタイプのインタフェースごとに1つではなく、実装が1つだけ必要です。

+0

Emm ...このような階層の簡単な例を教えてください。 – sharptooth

+0

'Base'と' Derived1' ... 'DerivedN'クラスのセットを仮定します。ここで' Derived'クラスはそれぞれ 'Interface1' ...' InterfaceM'のランダムサブセットを実装しています。 'Base :: QueryInterface'では、' this'が要求されたインターフェースに対して 'dynamic_cast'になるかどうかを調べます。 – MSalters

+0

さて、私はそれを見て、それは有効な例ですが、少し強くなっています。それを答えに含めてください。 – sharptooth

1

QueryInterface()は、実際には「動的キャスト」演算子の実装です。実装を同じメタデータ(継承ツリー)の別の変種を必要とする別の実装の上に置くことは本当の意味を持ちません。

良いコンパイラはこれをstatic_castに再マッピングできるはずです。

関連する問題