您的位置:首页 > 其它

COM学习笔记1_COM初步探索

2015-06-09 15:11 344 查看
COM组件的两个重要需求:
1。 动态链接
2。 隐藏实现细节

COM初步探索

一个典型C++客户和组件的例子

[cpp] view
plaincopy

// 组件模块  

interface IX  

{  

    virtual void __stdcall Fx1() = 0 ;  

    virtual void __stdcall Fx2() = 0 ;  

} ;  

interface IY  

{  

    virtual void __stdcall Fy1() = 0 ;  

    virtual void __stdcall Fy2() = 0 ;  

} ;  

// Interface implementation  

class CA : public IX,   

           public IY  

{  

//......  

} ;  

// 客户模块  

int main()  

{  

    CA* pA = new CA ;  

    pA->Fx1() ;  

    pA->Fx2() ;  

      

    pA->Fy1() ;  

    pA->Fy2() ;  

      

    delete pA ;  

}  

在COM中,推荐使用接口的指针来使用组件,上面客户端可以改成如下工作:

[cpp] view
plaincopy

// 客户模块  

int main()  

{  

    CA* pA = new CA ;  

    // Get an IX pointer.  

    IX* pIX = pA ;  

    pIX->Fx1() ;  

    pIX->Fx2() ;  

    // Get an IY pointer.  

    IY* pIY = pA ;  

    pIY->Fy1() ;  

    pIY->Fy2() ;  

    delete pA ;  

}  

接下来问题是:
1。 CA* pA = new CA ;
这里暴露太多细节,最起码客户需要类CA的头文件声明,这里把类CA的内部细节(私有成员)都暴露了,
而且当CA的实现细节改动,客户端肯定需要重新编译代码。
另外COM组件可能不在客户进程中,甚至在远程机器上,这样就不可能简单new出组件实例。

2。delete pA ;
这里需要显示释放组件。
但pIX和pIY也指向pA的对象,delete pA后如果再使用pIX等就会发生错误。
容易造成代码维护困难。

解决方案是所有接口派生自IUnknown。
IUnknown提供QueryInterface,AddRef和Release接口。
另外提供函数CreateInstance。

对于上面问题1,通过CreateInstance创建组件,并返回IUnknown接口指针,
然后通过QueryInterface再获取各种接口的指针。

对于上面问题2,每次获取组件指针时(自动)调用AddRef,该指针不再使用时调用Release。
组件内部维护引用计数,当计数为0时自动释放自己。这样就不需要手动new和delete了。

现在组件和客户代码如下:

[cpp] view
plaincopy

// 组件代码  

interface IX : IUnknown  

{  

    virtual void __stdcall Fx() = 0 ;  

} ;  

interface IY : IUnknown  

{  

    virtual void __stdcall Fy() = 0 ;  

} ;  

// Forward references for GUIDs  

extern const IID IID_IX ;  

extern const IID IID_IY ;  

class CA : public IX,  

           public IY  

{  

    virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv) ;            

    virtual ULONG __stdcall AddRef() { return 0 ;}  

    virtual ULONG __stdcall Release() { return 0 ;}  

    virtual void __stdcall Fx() { cout << "Fx" << endl ;}  

    virtual void __stdcall Fy() { cout << "Fy" << endl ;}  

} ;  

IUnknown* CreateInstance()  

{  

    IUnknown* pI = static_cast<IX*>(new CA) ;  

    pI->AddRef() ;  

    return pI ;  

}  

// 客户代码  

int main()  

{  

    IUnknown* pIUnknown = CreateInstance() ;  

    IX* pIX = NULL ;   

    if (SUCCEEDED (pIUnknown->QueryInterface(IID_IX, (void**)&pIX)))  

    {  

        pIX->Fx() ;          // Use interface IX.  

    }  

    IY* pIY = NULL ;  

    if (SUCCEEDED (pIUnknown->QueryInterface(IID_IY, (void**)&pIY)))  

    {  

        pIY->Fy() ;          // Use interface IY.  

        pIY->Release() ;  

    }  

    IY* pIYfromIX = NULL ;  

    if (SUCCEEDED (pIX->QueryInterface(IID_IY, (void**)&pIYfromIX)))  

    {     

        pIYfromIX->Fy() ;  

        pIYfromIX->Release() ;  

    }  

    pIX->Release() ;  

    pIUnknown->Release() ;  

}  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: