COM组件多接口对象模型
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组件多接口对象模型的更多相关文章
- COM组件双接口对象模型
模型如下: 这里COM对象一共实现了三个接口,IUnknown,IDispatch, Ixxx. 每个COM都必须实现IUnknown,不考虑在内的话共实现了IDispatch和自定义接口Ixxx两个 ...
- Android开发之自定义组件和接口回调
说到自定义控件不得不提的就是接口回调,在Android开发中接口回调用的还是蛮多的.在这篇博客开始的时候呢,我想聊一下iOS的自定义控件.在iOS中自定义控件的思路是继承自UIView, 在UIVie ...
- 【Android 应用开发】 自定义组件 宽高适配方法, 手势监听器操作组件, 回调接口维护策略, 绘制方法分析 -- 基于 WheelView 组件分析自定义组件
博客地址 : http://blog.csdn.net/shulianghan/article/details/41520569 代码下载 : -- GitHub : https://github.c ...
- COM组件三大接口IUnknown、IClassFactory、IDispatch。
转自:http://blog.csdn.net/chenyujing1234/article/details/7753863 (1)COM组件有三个最基本的接口类,分别是IUnknown.IClass ...
- DRF(2) - 解析器,序列化组件使用(GET/POST接口设计)
一.DRF - 解析器 1.解析器的引出 我们知道,浏览器可以向django服务器发送json格式的数据,此时,django不会帮我们进行解析,只是将发送的原数据保存在request.body中,只有 ...
- Restful 2 --DRF解析器,序列化组件使用(GET/POST接口设计)
一.DRF - 解析器 1.解析器的引出 我们知道,浏览器可以向django服务器发送json格式的数据,此时,django不会帮我们进行解析,只是将发送的原数据保存在request.body中,只有 ...
- django rest framework 解析器组件 接口设计,视图组件 (2)
1. 使用视图组件进行接口优化 1.1 使用视图组件的mixin进行接口逻辑优化 - 导入mixin from rest_framework.mixinx import ( ListModelMix, ...
- django rest framework 解析器组件 接口设计,视图组件 (1)
一.解析器组件 -解析器组件是用来解析用户请求数据的(application/json), content-type 将客户端发来的json数据进行解析 -必须适应APIView -request.d ...
- C++ 类的动态组件化技术
序言: N年前,我们曾在软件开发上出现了这样的困惑,用VC开发COM组件过于复杂,用VB开发COM组件发现效率低,而且不能实现面向对象的很多特性,例如,继承,多态等.更况且如何快速封装利用历史遗留的大 ...
随机推荐
- 5.Android之NFC介绍
NFC简介: Near Field Communication 近场通信,是一种数据传输技术. 与wifi.蓝牙.红外线等数据传输技术的一个主要差异就是有效距离一般不能超过4cm. NFC支持3种工作 ...
- sql server 2005 链接服务器:未将服务器 配置为用于 RPC
原文:sql server 2005 链接服务器:未将服务器 配置为用于 RPC RPC: 远程过程调用(Remote Procedure Calls) --LinkedServer.Rpc 属性: ...
- IMAP 命令
最近学习了一下IMAP命令,现在也算总结一下学习的东西,先说说IMAP命令,如果你使用的是163.126邮箱,反正是网易家的邮箱,那么这里就有很多坑要踩了,因为网易邮箱的特殊性,由于网易邮箱在中国占有 ...
- 基于物品过滤的Slope One 算法
Slope One 算法是由 Daniel Lemire 教授在 2005 年提出的一个 Item-Based 推荐算法. 他的主要优点是简单,易于扩展.实际上有多个Slope One算法,在此主要学 ...
- hdu1021(C++)
打表找规律,发现是n%4==2就是yes,否则是no #include<iostream>using namespace std;int main(){ int n; while (cin ...
- sql cast函数
一.语法: CAST (expression AS data_type) 参数说明: expression:任何有效的SQLServer表达式. AS:用于分隔两个参数,在AS之前的是要处理的数据,在 ...
- 关于RBAC(Role-Base Access Control)的理解
基于角色的访问控制(Role-Base Access Control) 有两种正在实践中使用的RBAC访问控制方式:隐式(模糊)的方式和显示(明确)的方式. 今天依旧有大量的软件应用是使用隐式的访问控 ...
- vs2015安装VAssistX以后,去除中文注释会有红色下划线方法
---恢复内容开始--- 环境:Visual Studio 2015 问题:代码中出现中文后会带下划线,不舒服-----解决办法. 1.安装完Visual Assist X后会在VS2015的菜单栏出 ...
- django xadmin的使用和改造
django本身自带一个强大的admin后台管理系统,但是管理起来并不是很方便.这里介绍下xadmin,xadmin是基于bootstrap和admin的一个更强大的后台管理系统 github地址ht ...
- Linux取消挂载,删除用户及其目录
取消挂载 取消挂载命令: umount /dev/sdb 命令umount 文件系统/挂载点 umount /dev/sdb 例如:umount /dev/sdb即可将sdb1取消挂载. 如果出现de ...