博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
interface——关于虚函数的内存分配
阅读量:5146 次
发布时间:2019-06-13

本文共 1889 字,大约阅读时间需要 6 分钟。

之前学C++的时候了解到,其中很多控件是基于com的,今天初学接口,写了一小段测试程序

接口为IX,IY

组件为CA,(继承于IX和IY)

客户为main函数

 

流程如下:

 

 

接口连接组件的功能是由虚函数实现的

一般来说,父类作为接口,子类作为组件,子类实现父类的功能(组件实现接口所要求的功能)

虚函数就是实现这一过程的方法

对于虚函数在内存中的分配,下面是个小测试程序:

1 #include
2 using namespace std; 3 class CA 4 { 5 public: 6 int i; 7 virtual void __stdcall virtualFun()=0; 8 }; 9 10 class CASub:public CA11 {12 virtual void __stdcall virtualFun()13 {14 return;15 }16 };17 18 class CB19 {20 public:21 int i;22 };23 24 void main()25 {26 CASub *pA = new CASub;27 CB *pB = new CB;28 cout<<"pA Address:"<
<
i)<
i)<

运行结果如下图

由此可见pA(由CASub产生,CASub又是由CA继承而来)的长度为8个字节,pA中有虚函数和int类型

pB(由CB产生)的长度为4个字节,其中pB中只有int类型,因此知道虚函数占用的是4个字节,

不过虚函数中并没有数据,因此该4个字节应该是虚函数的地址,

另外,程序中虚函数是写在int后的,而到了内存中虚函数却在前面,由此可以判定是编译器故意为之,为了提高虚函数调用的速度。

 

然后我们来看一下接口地址和组件地址的关系,

组件是CA,接口为IX和IY,

测试代码如下

1 #include
2 #include
3 using namespace std; 4 void trace(const char* pMsg) 5 { 6 cout<
<
Fx1();43 pIX->Fx2();44 45 IY* pIY=pA;46 trace("Client:Use the IY interface.");47 pIY->Fy1();48 pIY->Fy2();49 50 51 cout<

运行结果

CA继承于IX和IY,由运行结果可以看出pA地址跟pIX一致,这也是继承的特性,构造CA的时候会先构造父类IX,然后构造IY;

组件CA在内存中的大小为8字节,接口各4个字节,而接口作为内部有虚函数的类,虚函数地址就占了4个字节,并且每个接口有两个函数,

 

 据书上的说法,虚函数的实现是,内存中首个4BYTE包含的是指向虚函数表的指针,然后再在表中包含指向实现该虚函数的实际内存地址,如下图:

 注:接口的内存结构对于不同的操作系统可能是不同的,例如在mac上,vtbl指针将指向一个伪指针,而第一个函数指针则位于第二个表项中

 

假设子类不含有虚函数Fx1,那么就会把父类的虚函数的入口地址写到子类虚函数表的Fx1处,如果子类存在虚函数Fx1,那么该处就填子类Fx1的入口地址,

对于所有不含有Fx1的子类,而父类有Fx1,那么所有子类将共用该函数的代码段

 

在学习过程中,本人发现了类中的静态数据类型(static)必须在外部重新定义一遍

如:

class A{public: static int i;};

手动定义一遍,int A::i=0;这个时候才会进行 i 的内存分配

另外还有一个问题是上面的这条int A::i=0;无法放在main 函数中,原因估计是作为类中静态变量,同时也是全局变量,必须时刻都在内存中

由于水平有限,上面部分为推测,如有错误欢迎留言纠正

转载于:https://www.cnblogs.com/TaigaCon/archive/2012/07/14/2591039.html

你可能感兴趣的文章
基于wxPython的python代码统计工具
查看>>
淘宝JAVA中间件Diamond详解(一)---简介&快速使用
查看>>
一种简单的数据库性能测试方法
查看>>
如何给JavaScript文件传递参数
查看>>
Hadoop HBase概念学习系列之物理视图(又名为物理模型)(九)
查看>>
Hadoop HBase概念学习系列之HBase里的宽表设计概念(表设计)(二十七)
查看>>
Kettle学习系列之Kettle能做什么?(三)
查看>>
ExtJS 4.2 业务开发(一)主页搭建
查看>>
webpack Import 动态文件
查看>>
电脑没有安装iis,但是安装了.NET环境,如何调试网站发布的程序
查看>>
【Mac + GitHub】之在另一台Mac电脑上下载GitHub的SSH链接报错
查看>>
Day03:Selenium,BeautifulSoup4
查看>>
Java NIO系列教程(九) ServerSocketChannel
查看>>
awk变量
查看>>
mysql_对于DQL 的简单举例
查看>>
postgis几何操作函数集
查看>>
ACM题目————还是畅通工程
查看>>
CentOS7使用firewalld打开关闭防火墙与端口
查看>>
35. Search Insert Position(C++)
查看>>
ubuntu 卡在登陆界面无法进入桌面,但是可以进入命令行界面
查看>>