收藏一个例子,摘自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 是否也可以这样,这点我就没试过了,如果各位读者知道为何的话,还请不啬指点一二哈 ~~