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

接口图如下:

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

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

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

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

 #include <iostream>
using namespace std; class IUnknown
{
public:
virtual long QueryInterface( long riid, void * * ppvObject) = ;
virtual long AddRef( void) = ;
virtual long Release( void) = ;
}; class IMyMath : public IUnknown
{
public:
virtual long Add(long n1, long n2, long* pVal) = ;
}; class IStr : public IUnknown
{
public:
virtual long Cat(char* _Dest, const char* _Source) = ;
}; class CMyTest: public IMyMath, public IStr
{
public:
long QueryInterface( long riid, void * * ppvObject) { cout<<"QueryInterface"<<endl; return ;}
long AddRef( void) { cout<<"AddRef"<<endl; return ;}
long Release( void) { cout<<"Release"<<endl; return ;} long Add(long n1, long n2, long* pVal) { cout<<"Add"<<endl; return ;}
long Cat(char* _Dest, const char* _Source){ cout<<"Cat"<<endl; return ;}
}; typedef long (*QueryInterfaceType)( long riid, void * * ppvObject);
typedef long (*AddRefType)( void);
typedef long (*ReleaseType)( void); typedef long (CMyTest::*QueryInterfaceClassType)( long riid, void * * ppvObject); void main()
{
CMyTest * pTest = new CMyTest;
//pTest->AddRef(); int* pFirst = (int*)( *(int*)(pTest)); cout<<"IMyMath virtual table call"<<endl;
for(int i=; i<; i++)
{
((QueryInterfaceType)(*(pFirst+i)))(, NULL);
cout<<int((QueryInterfaceType)(*(pFirst+i)))<<endl;
} cout<<endl<<"--------------------------------------------------"<<endl<<endl; cout<<"IStr virtual table call"<<endl;
for(int i=; i<; i++)
{
int* pFirst2 = (int*)( *((int*)(pTest)+));
((QueryInterfaceType)(*(pFirst2+i)))(, NULL);
cout<<int((QueryInterfaceType)(*(pFirst2+i)))<<endl;
}
}

后记:

之前提出一个问题,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

COM组件多接口对象模型的更多相关文章

  1. COM组件双接口对象模型

    模型如下: 这里COM对象一共实现了三个接口,IUnknown,IDispatch, Ixxx. 每个COM都必须实现IUnknown,不考虑在内的话共实现了IDispatch和自定义接口Ixxx两个 ...

  2. Android开发之自定义组件和接口回调

    说到自定义控件不得不提的就是接口回调,在Android开发中接口回调用的还是蛮多的.在这篇博客开始的时候呢,我想聊一下iOS的自定义控件.在iOS中自定义控件的思路是继承自UIView, 在UIVie ...

  3. 【Android 应用开发】 自定义组件 宽高适配方法, 手势监听器操作组件, 回调接口维护策略, 绘制方法分析 -- 基于 WheelView 组件分析自定义组件

    博客地址 : http://blog.csdn.net/shulianghan/article/details/41520569 代码下载 : -- GitHub : https://github.c ...

  4. COM组件三大接口IUnknown、IClassFactory、IDispatch。

    转自:http://blog.csdn.net/chenyujing1234/article/details/7753863 (1)COM组件有三个最基本的接口类,分别是IUnknown.IClass ...

  5. DRF(2) - 解析器,序列化组件使用(GET/POST接口设计)

    一.DRF - 解析器 1.解析器的引出 我们知道,浏览器可以向django服务器发送json格式的数据,此时,django不会帮我们进行解析,只是将发送的原数据保存在request.body中,只有 ...

  6. Restful 2 --DRF解析器,序列化组件使用(GET/POST接口设计)

    一.DRF - 解析器 1.解析器的引出 我们知道,浏览器可以向django服务器发送json格式的数据,此时,django不会帮我们进行解析,只是将发送的原数据保存在request.body中,只有 ...

  7. django rest framework 解析器组件 接口设计,视图组件 (2)

    1. 使用视图组件进行接口优化 1.1 使用视图组件的mixin进行接口逻辑优化 - 导入mixin from rest_framework.mixinx import ( ListModelMix, ...

  8. django rest framework 解析器组件 接口设计,视图组件 (1)

    一.解析器组件 -解析器组件是用来解析用户请求数据的(application/json), content-type 将客户端发来的json数据进行解析 -必须适应APIView -request.d ...

  9. C++ 类的动态组件化技术

    序言: N年前,我们曾在软件开发上出现了这样的困惑,用VC开发COM组件过于复杂,用VB开发COM组件发现效率低,而且不能实现面向对象的很多特性,例如,继承,多态等.更况且如何快速封装利用历史遗留的大 ...

随机推荐

  1. Android SDK 目录说明

    Android SDK目录说明: AVD Manager.exe:虚拟机管理工具 SDK Manager.exe:sdk管理工具 tools目录:包括测试.调试.第三方工具.模拟器.数据管理工具等. ...

  2. DirectoryServicesCOMException

    捕捉到 System.DirectoryServices.DirectoryServicesCOMException Message=该服务器不愿意处理该请求. Source=System.Direc ...

  3. 对于session序列化跟session的钝化与活化的粗浅理解

    1. API对序列化的解释:类通过实现 java.io.Serializable 接口以启用其序列化功能.未实现此接口的类将无法使其任何状态序列化或反序列化.可序列化类的所有子类型本身都是可序列化的. ...

  4. 在Centos7.x中安装psutil模块

    一.window10操作系统(Python 3.6开发环境)安装psutil 1.安装psutil模块 wget https://pypi.python.org/packages/source/p/p ...

  5. sass高级语法的补充

    1. 继承 2.混入 3.函数 我这篇博客需要点基础才能看懂, 但我这篇博客是对上一篇的 sass高级语法 的补充 从这方面来看也无所谓了

  6. C++ 大规模数据排序(100G数据 使用 4G 内存 排序)

    思路很简单,先分段排序,存储到临时文件中,然后合并. 使用10000个整数来模拟大数据,每次读取100个到内存中. #include <stdint.h> #include <std ...

  7. C++Singleton的DCLP(双重锁)实现以及性能测评

      本文系原创,转载请注明:http://www.cnblogs.com/inevermore/p/4014577.html   根据维基百科,对单例模式的描述是: 确保一个类只有一个实例,并提供对该 ...

  8. 【Excle数据透视表】如何在Excle中使用数据鼠标拖放

    数据透视表建立好之后,我们有时候需要改动数据透视表,那么直接可以对字段进行拖拽就可以改变,这样使数据透视变得比较方便使用 原始样式 拖拽后样式 步骤 右键数据透视表任意单元格→数据透视表选项→显示→经 ...

  9. 【BIEE】分析的解析机制

    今天使用BIEE时意外的发现个问题,BIEE在展示结果时候,是先进行排序,然后再展示.具体测试案例如下: 首先,存在如下数据: 在BIEE展示效果如下: 目前是根据O1,02,03,04,05,06, ...

  10. 键盘上所有键位的ascii值

    上次用的时候一直找,这次找到了,收藏起来. 0x1 鼠标左键 0x2 鼠标右键 0x3 CANCEL 键 0x4 鼠标中键 0x8 BACKSPACE 键 0x9 TAB 键 0xC CLEAR 键 ...