COM组件多接口对象模型

COM组件有两种接口类型,Dual and Custom,如下图所示。本文说的是Custom。所谓多接口COM对象是指此COM对象实现了多于一个的自定义接口,即Custom接口。

 

接口图如下:

需要注意的是最终实现的COM对象用的不是虚继承而是普通的多继承,因为被多继承的IUnknown接口是不含任何数据成员,只有纯虚函数,继承的子接口也是这样。还有为了实现跨语言或平台的调用,最终没用虚继承。更多的原因请参考本文最后的链接。

这里给出多接口COM对象的模型:

 

很清楚地看到COM是实现了两个接口,也就是多继承子两个父接口,有两个虚函数表,其中IUnknown的三个函数指针在两个虚函数表里都各有一份。但是从我下面的打印结果来看指向的地址不太一样,不是很清楚真正的COM对象是怎么实现的。留着以后再研究吧。

 

示例程序。使用时会有assert dialog弹出来,直接点忽略就行了。

 1 #include <iostream>
 2 using namespace std;
 3 
 4 class  IUnknown
 5 {
 6 public:
 7     virtual long  QueryInterface(  long riid, void * * ppvObject) = 0;
 8     virtual long  AddRef( void) = 0;
 9     virtual long  Release( void) = 0;
10 };
11 
12 class  IMyMath :  public IUnknown
13 {
14 public:
15     virtual long Add(long n1, long n2, long* pVal) = 0;
16 };
17 
18 class  IStr :  public IUnknown
19 {
20 public:
21     virtual long Cat(char* _Dest, const char* _Source) = 0;
22 };
23 
24 class CMyTest: public IMyMath, public IStr
25 {
26 public:
27     long  QueryInterface(  long riid, void * * ppvObject) { cout<<"QueryInterface"<<endl; return 1;}
28     long  AddRef( void) { cout<<"AddRef"<<endl; return 1;}
29     long  Release( void) { cout<<"Release"<<endl; return 1;}
30 
31     long Add(long n1, long n2, long* pVal) { cout<<"Add"<<endl; return 1;}
32     long Cat(char* _Dest, const char* _Source){ cout<<"Cat"<<endl; return 1;}
33 };
34 
35 typedef long  (*QueryInterfaceType)(  long riid, void * * ppvObject);
36 typedef long  (*AddRefType)( void);
37 typedef long  (*ReleaseType)( void);
38 
39 typedef long  (CMyTest::*QueryInterfaceClassType)(  long riid, void * * ppvObject);
40 
41 void main()
42 {
43     CMyTest * pTest = new CMyTest;
44     //pTest->AddRef();
45 
46     int* pFirst = (int*)( *(int*)(pTest));
47 
48     cout<<"IMyMath virtual table call"<<endl;
49     for(int i=0; i<4; i++)
50     {
51         ((QueryInterfaceType)(*(pFirst+i)))(0, NULL);
52         cout<<int((QueryInterfaceType)(*(pFirst+i)))<<endl;
53     }
54 
55     cout<<endl<<"--------------------------------------------------"<<endl<<endl;
56 
57     cout<<"IStr virtual table call"<<endl;
58     for(int i=0; i<4; i++)
59     {
60         int* pFirst2 = (int*)( *((int*)(pTest)+1));
61         ((QueryInterfaceType)(*(pFirst2+i)))(0, NULL);
62         cout<<int((QueryInterfaceType)(*(pFirst2+i)))<<endl;
63     }
64 }

 

 

后记:

之前提出一个问题,IUnknown的三个函数地址在两个虚函数表里都各有一份,但是地址值打印出来不一样,用VS command prompt打印class layout如下图,下面的IStr的虚函数表里多了个this -= 4,这里的4是IStr与实际对象指针也就是this指针的偏移量。

 

 参考文章:

http://bbs.csdn.net/topics/390223914

http://blog.csdn.net/wxc1987821/article/details/5958325

转载于:https://www.cnblogs.com/dirichlet/p/3236322.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值