请高手讲解一下com中的包容与聚合,我在看vc技术内幕,这地方看的有点不明白.

解决方案 »

  1.   

    包含和聚合只是代码重用中的两种方法,与COM无关,是一种算法,只不过COM中大量使用聚合,才使得起其重要性增加
    包含很简单:
    struct OBJECT
    {
        long SomeThing;
    };
    struct CONTAINER
    {
        OBJECT Object;
    };
    就说CONTAINER这个结构包含了OBJECT这个结构,既在C中我们就大量使用了包含这个技术。
    再如:
    class CEmail
    {
        CStringW m_ShowName;  // 显示名称
        CStringW m_Add;       // 装Email地址
    };
    CEmail email;
    则说email通过包含而重用了两个CStringW对象聚合不常见,所以容易昏
    class A
    {
    // 操作
    public:
        void A();
        void AA();// 成员变量
    private:
        ...
    };
    class B
    {
    // 操作
    public:
        void B();
        void A()   { m_A.A(); }
        void AA()  { m_A.AA(); }// 成员变量
    private:
        ...
        A m_A;
    };
    就说B聚合了A,如果
    B g_B;
    就说g_B通过聚合而重用了g_B.m_A,即是说聚合表示伪装,它让外界看起来它支持A()和AA(),实际它不支持,而是在内部秘密的要挟m_A来帮它完成任务,之所以被认为聚合,因为它将两个的类的功能合在了一个类中。与包容的区别就是包容不会暴露被重用的接口(即A(),AA())。
    如果你仔细看过书,会发现书上将我上面说的聚合称作包容。不一样,我上面那种其实是静态聚合,既聚合的功能不能动态改变(要变就得重编代码),下面是COM中用到的聚合,是动态聚合
    class C : public IUnknown
    {
    // 构造
    public:
        C( IUnknown *pUnk ) : m_pUnk( pUnk )
        {
        }// 其他重载IUnknown的成员
    // 成员变量
    private:
        IUnknown *m_pUnk;
    };
    这样,C就动态聚合了从构造函数传入的m_pUnk的接口(既C现在对外宣称支持m_pUnk所指之对象所支持的接口),这通过QueryInterface来实现
    HRESULT C::QueryInterface( REFIID iid, void **pVoid )
    {
        if( iid == IID_IUnknown )
            *pVoid = static_cast< IUnknown* >( this );
        else
            if( m_pUnk && SUCCEEDED( m_pUnk->QueryInterface( iid, pVoid ) ) )
                return S_OK;
            else
                return E_FAIL;    return S_OK;
    }
    此时,可以写
    extern IDispatch *g_pDisp;
    C g_C( g_pDisp );
    IDispatch *g_pD = NULL;
    HRESULT hr =
         g_C.QueryInterface( IID_IDispatch, reinterpret_cast< void** >( &g_pD ) );
    ASSERT( SUCCEEDED( hr ) );  // g_C也支持IDispatch*,
                                // 而实现C时根本不知道有IDispatch这么一个东西因此,不是随便的QueryInterface的实现都可支持聚合的,所以ATL的向导同意你在实现COM对象时选择是否支持聚合。注意,这里应该说成被聚合才对,即选了选项后生成的COM对象将可以被别的COM对象(可以是不支持聚合的对象)聚合。
    COM中的许多地方都用到聚合,如代理/占位程序中。
      

  2.   

    《ATL开发指南》第五章里面有一个很好的具体实例可以帮助你尽快理解包容和聚合的区别和实现
      

  3.   

    如果需要关于包容和聚合的DEMO,我这里有 !
      

  4.   

    看看lostall的说法,你看了图解会跟清楚,还有很多文章:http://comcamp.myrice.com/techarticles/com/2021.htm