最简单的COM实现例子

收藏一个例子,摘自http://www.cnblogs.com/gamedes/archive/2013/01/17/2863964.html#2602071

#include "stdio.h"

class IUnknow
{
public: 
 virtual void * QueryInterface( int _type ) = 0;
 virtual void addRef( void ) = 0;
 virtual void release( void ) = 0;
};

class IX : public IUnknow
{
public: 
 virtual void X1( void ) = 0;
 virtual void X2( void ) = 0;
};

class IY : public IUnknow
{
public:
 
 virtual void Y1( void ) = 0;
 virtual void Y2( void ) = 0;
};


class CA : public IX, public IY
{
public: 
    CA( ) : m_ref( 0 ) { }
 
public: 
    void * QueryInterface( int _type )
    {
        void * _interface = NULL;
  
        if( 1 == _type ) _interface = static_cast< IX * >( this );
        else if( 2 == _type ) _interface = static_cast< IY * >( this );
  
        if( _interface ) static_cast< IUnknow * >( _interface )->addRef( );
        return _interface;
    }
 
    void addRef( void ){ m_ref ++; }
    void release( void )
 {
  m_ref --; 
  if( m_ref <= 0 )
  { 
   delete this; 
   printf( "Component destroy ... \n" ); 
  } 
 }
 
    void X1( void ){ printf( "X1( )\n" ); }
    void X2( void ){ printf( "X2( )\n" ); }
    void Y1( void ){ printf( "Y1( )\n" ); }
    void Y2( void ){ printf( "Y2( )\n" ); }
 
private: 
    int m_ref;
};

IUnknow * CreateInstance( void )
{
    IUnknow * _interface = static_cast< IX * >( new CA );
 
    _interface->addRef( );
 
    return _interface;
}

int main( int argc, char * argv[ ] )
{
    IUnknow * obj = CreateInstance( );
    {
        IX * ix = ( IX * ) obj->QueryInterface( 1 );
        {
            ix->X1( );
            ix->X2( );
        }
        ix->release( );
  
        IY * iy = ( IY * ) obj->QueryInterface( 2 );
        {
            iy->Y1( );
            iy->Y2( );
        }
        iy->release( );
    }
    obj->release( );
 
    return 0;
}

我还是解释一下吧 :

IUnknow 是所有接口的祖先,因此,任何一个接口,都可以通过 QueryInterface 来获得一个组件所支持的所有其它接口 。

addRef 和 release 用于统计引用计数器,来控制组件的生命周期 。

CA 就是我们的接口实现主体,也就是接口的集合,我们称它作 —— 组件 。

CreateInstance 用于创建我们的组件,它相当于我们 D3D 的 Direct3DCreate9  这样子的函数,嗯 ... hgeCreate 也是这样子的函数(笑) 。

最后最重要的一条 :

IX 和 IY 才是接口,才是我们客户能够进行交互的实体,因为对于客户来说,CA 组件是不可见的,客户只知道拥有 IX 和 IY 接口,其余东西,都是透明的 。

当然,真正的 COM 可不会像这个样子,它至少,还需要一个 GUID 啊、CLSID 啊、IID 之类的东西,不过我上面都用 1 和 2 简单地代替了 。

其次,我有一个疑惑,就像上面的代码里面,在查询得到 IX 接口之后, CA 的引用计数器应该为 2,我们用完了 IX 接口,release 一次之后,CA 的引用计数器应该为 1,此时 CA 还没有被销毁,我们应该还能继续使用 IX 接口,但是真正的 COM 是否也可以这样,这点我就没试过了,如果各位读者知道为何的话,还请不啬指点一二哈 ~~ 

原文地址:https://www.cnblogs.com/Roarsun/p/2864571.html