C++类内存对象模型
来源:互联网 发布:mac星球基地中文版 编辑:程序博客网 时间:2024/04/29 07:53
前言
07年12月,我写了一篇《C++虚函数表解析》的文章,引起了大家的兴趣。有很多朋友对我的文章留了言,有鼓励我的,有批评我的,还有很多问问题的。我在这里一并对大家的留言表示感谢。这也是我为什么再写一篇续言的原因。因为,在上一篇文章中,我用了的示例都是非常简单的,主要是为了说明一些机理上的问题,也是为了图一些表达上方便和简单。不想,这篇文章成为了打开C++对象模型内存布局的一个引子,引发了大家对C++对象的更深层次的讨论。当然,我之前的文章还有很多方面没有涉及,从我个人感觉下来,在谈论虚函数表里,至少有以下这些内容没有涉及:
1)有成员变量的情况。
2)有重复继承的情况。
3)有虚拟继承的情况。
4)有钻石型虚拟继承的情况。
这些都是我本篇文章需要向大家说明的东西。所以,这篇文章将会是《C++虚函数表解析》的一个续篇,也是一篇高级进阶的文章。我希望大家在读这篇文章之前对C++有一定的基础和了解,并能先读我的上一篇文章。因为这篇文章的深度可能会比较深,而且会比较杂乱,我希望你在读本篇文章时不会有大脑思维紊乱导致大脑死机的情况。;-)
对象的影响因素
简而言之,我们一个类可能会有如下的影响因素:
1)成员变量
2)虚函数(产生虚函数表)
3)单一继承(只继承于一个类)
4)多重继承(继承多个类)
5)重复继承(继承的多个父类中其父类有相同的超类)
6)虚拟继承(使用virtual方式继承,为了保证继承后父类的内存布局只会存在一份)
上述的东西通常是C++这门语言在语义方面对对象内部的影响因素,当然,还会有编译器的影响(比如优化),还有字节对齐的影响。在这里我们都不讨论,我们只讨论C++语言上的影响。
本篇文章着重讨论下述几个情况下的C++对象的内存布局情况。
1)单一的一般继承(带成员变量、虚函数、虚函数覆盖)
2)单一的虚拟继承(带成员变量、虚函数、虚函数覆盖)
3)多重继承(带成员变量、虚函数、虚函数覆盖)
4)重复多重继承(带成员变量、虚函数、虚函数覆盖)
5)钻石型的虚拟多重继承(带成员变量、虚函数、虚函数覆盖)
我们的目标就是,让事情越来越复杂。
知识复习
我们简单地复习一下,我们可以通过对象的地址来取得虚函数表的地址,如:
我们同样可以用这种方式来取得整个对象实例的内存布局。因为这些东西在内存中都是连续分布的,我们只需要使用适当的地址偏移量,我们就可以获得整个内存对象的布局。
本篇文章中的例程或内存布局主要使用如下编译器和系统:
1)Windows XP
2)Cygwin
单一的一般继承
下面,我们假设有如下所示的一个继承关系:
请注意,在这个继承关系中,父类,子类,孙子类都有自己的一个成员变量。而了类覆盖了父类的f()方法,孙子类覆盖了子类的g_child()及其超类的f()。
我们的源程序如下所示:
class
public:
};
class
public:
};
class
public:
};
我们使用以下程序作为测试程序:(下面程序中,我使用了一个int** pVtab
其运行结果如下所示:(在VC++ 2003和G++ 3.4.4下)
[0] GrandChild::_vptr->
[1] Parent.iparent = 10
[2] Child.ichild = 100
[3] GrandChild.igrandchild = 1000
使用图片表示如下:
可见以下几个方面:
1)虚函数表在最前面的位置。
2)成员变量根据其继承和声明顺序依次放在后面。
3)在单一的继承中,被overwrite的虚函数在虚函数表中得到了更新。
多重继承
下面,再让我们来看看多重继承中的情况,假设有下面这样一个类的继承关系。注意:子类只overwrite了父类的f()函数,而还有一个是自己的函数(我们这样做的目的是为了用g1()作为一个标记来标明子类的虚函数表)。而且每个类中都有一个自己的成员变量:
我们的类继承的源代码如下所示:父类的成员初始为10,20,30,子类的为100
class
public:
};
class
public:
};
class
public:
};
class
public:
};
我们通过下面的程序来查看子类实例的内存布局:下面程序中,注意我使用了一个s变量,其中用到了sizof(Base)来找下一个类的偏移量。(因为我声明的是int成员,所以是4个字节,所以没有对齐问题。关于内存的对齐问题,大家可以自行试验,我在这里就不多说了)
其运行结果如下所示:(在VC++ 2003和G++ 3.4.4下)
[0] Base1::_vptr->
[1] Base1.ibase1 = 10
[2] Base2::_vptr->
[3] Base2.ibase2 = 20
[4] Base3::_vptr->
[5] Base3.ibase3 = 30
[6] Derive.iderive = 100
使用图片表示是下面这个样子:
我们可以看到:
1)
2)
3)
4)
博文转自:http://blog.csdn.net/haoel/article/details/3081328
- 【C++】C++对象内存模型简介
- 漫谈C++:对象内存模型分析
- C++-对象继承内存模型配图
- 类、对象的内存模型
- C++类对象内存模型
- C++类内存对象模型
- c++类对象的内存模型
- c++类对象的内存模型
- c++类对象的内存模型
- c++类对象的内存模型
- c++类对象的内存模型
- c++类对象的内存模型
- c++类对象的内存模型
- C++类对象的内存模型
- C++类对象的内存模型
- 谈VC++对象模型(类内存占用)
- C++类对象的内存模型
- C++类对象内存模型2
- DXP中PCB各层的作用
- [转] iOS --- ReactiveCocoa - iOS开发的新框架
- XML & JSON
- 南邮OJ 1013 判断三角形
- 关于Android Studio替换为同名图片后,运行报错问题解决办法
- C++类内存对象模型
- python -简单的数据库支持
- eclipse,tomcat内存溢出内存溢出解决办法查看内存
- Git发生SSL certificate problem: certificate ha错误的解决方法
- mongodb增删改查操作汇总
- jQuery对象与DOM对象之间的转换方法
- properties配置文件的读取工具类
- 解决办法:matlab Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap
- 随时总结日常好用的方法