INondelegationUniknownインターフェース

3037 ワード

原文の住所:http://hi.baidu.com/sanvy4116/blog/item/0a4159d08e118b88a0ec9ce4.html
class CA : public IA, public INondelegationUnknown, public IB
{
  ...
};
// IA,IB      IUnknown
HRESULT CA::NondelegationQueryInterface(const GUID& iid, void **ppv)
{
  *ppv = NULL;
  if (iid == IID_IA) {
    *ppv = (IA*)this; //      
    ((IA*)(*ppv))->AddRef(); //       ,     ,     ,       
    return S_OK;
  }
  else if (iid == IID_IB) {
    *ppv = (IB*)this;
    ((IB*)(*ppv))->AddRef(); //       ,     ,     ,       
    return S_OK;
  }
  else if (iid == IID_IUnknown) {
    *ppv = (INondelegationUnknown*)this; //      (          )
    ((IUnknown*)(*ppv))->AddRef(); //       NondelegationAddRef,              ,      NondelegationAddRef,            IUnknow     
    return S_OK;
  }
  return E_NOINTERFACE; 
}
INondelegationUnknown接口_第1张图片図において、pCAはCAタイプのポインタであり、CA、IAとIUnknownタイプの同じインスタンスのポインタ値は同じであり(0 x 0044213 c)、この例はメモリ位置の最初に、INondelegationUniknownはその後、IBはさらに後ろにあり、ポインタタイプをINondelegationUniknownタイプに変換した後、ポインタタイプを再起動する.実際には、NondelegationAddrefを呼び出していますが、INondelegationUniknownインターフェースの関数順がIUniknownと一致しない場合、エラーが発生します.重合に使用する場合、コンポーネントが作成された後、その外部インターフェースのポインタは空ではなく、そのIUnknow関数を呼び出した時、IUnknow関数を依頼すると、いつもpOutが指す関数に送られます.IUKnownは、非プロキシの関数呼び出しを取得します.(IBタイプのIUnknown関数は、実際には前のIAのIUnknown関数にジャンプしたThunkコードであり、それは本当の実現位置であり、CAはIA、IBのIUniknownの実現は一部のみである).コンポーネントを統合して使用するには、外部コンポーネントは、顧客が内部コンポーネントを提供するインターフェースを必要とするときにのみ、内部コンポーネントへの呼び出しをINondelegation:Query Interfaceに切り替えるべきであり、外部コンポーネントは、内部コンポーネントに統合するために使用するインターフェースを申請してはならない.以下は集約的に使用される例である.
void AggregateClass::QueryInterface(const GUID& iid, void **ppv)
{
  if (iid == IID_IA || iid == IID_IB)
    return pInner->QueryInterface(); //            ,            。
  else
    //          ,  IUnknown
}
AgregateClassは外部コンポーネントであり、pInnerは内部コンポーネント(CA)のIUnknownポインタであり、実際にINondelegationUniknown関数を指す.お客様が内部コンポーネントの実装インターフェースを必要とする時、お客様はこのインターフェースがどこで実現されたのかよく分かりません.外部コンポーネントから取得したポインタを使って照会します.このインターフェースが内部で実現された時、外部コンポーネントは直接にコンポーネントのINondelegationを呼び出すことができます.このときユーザに提供されるインターフェースポインタは、このような要求を満たす必要があります.つまり、外部コンポーネントのです.これはなぜですか?NondelgationQueryInterfaceでは、IUnknownインターフェースのポインタを申請する時に、非委託のIUnknownである以外のインターフェースはすべて委託されています.実際に依頼するのは、これらのインターフェースを申請するのはクライアントに違いないです.2.なぜ「IUnknownインターフェースを申請するのは必ず外部のコンポーネントです」というのか?集約する時、外部のコンポーネントは自分でIUnknownインターフェースを持っています.これはお客様がIUnknownを申請する時に、重合使用のコンポーネントに要求を送りません.それは内部の部品のIUKnowインターフェースを申請して一つの作用だけあって、重合して使います.(前に述べた)3.非プロキシIUKnown関数により、内部コンポーネントの生存周期を制御することができます.また、1つのコンポーネントが統合能力を提供するには、内部の非プロキシInnown関数の2つのセットを実現しなければならない.