C++继承内存对象模型
来源:互联网 发布:centos 创建用户组 编辑:程序博客网 时间:2024/05/17 03:02
最近研究了一下,C++继承的内存对象模型。主要是读了读http://blog.csdn.net/haoel/article/details/3081328(C++ 对象的内存布局)。很推荐这篇文章。
对这篇文章做了做总结。本文的大部分内容来自于这篇文章中的总结http://blog.csdn.net/haoel/article/details/3081328(C++ 对象的内存布局)。
分为四种情况:
1.单继承
2.多继承(不含钻石继承)
3.非虚继承的钻石继承
4.虚继承的钻石继承
注:下面所有类中的函数都是虚函数。
1.单继承
单继承体系如下:
GrandChild对象的内存布局:
可见以下几个方面:
1)虚函数表在最前面的位置。
2)成员变量根据其继承和声明顺序依次放在后面。
3)在单一的继承中,被overwrite的虚函数在虚函数表中得到了更新。
2.多继承
多继承的体系如下:
Derive对象的内存布局如下:
我们可以看到:
1) 每个父类都有自己的虚表。
2) 子类的成员函数被放到了第一个父类的表中。
3) 内存布局中,其父类布局依次按声明顺序排列。
4) 每个父类的虚表中的f()函数都被overwrite成了子类的f()。这样做就是为了解决不同的父类类型的指针指向同一个子类实例,而能够调用到实际的函数。出现钻石继承的虚继承的时候,虚基类在子类中只有一份。
出现钻石继承的非虚继承的时候,虚基类在每个子类中都有一份。
3.非虚继承的钻石继承
继承体系如下:D的内存布局如下:
红色的部分就是重复的部分,就会造成二义性
4.虚继承的钻石继承(虚继承就是解决钻石继承问题的,如果不存在钻石继承,就不用虚继承)
继承体系如下:(红色专门标准虚继承)
D的内存布局如下:
可以看出,少了重合的部分。但是,代价是增加了一个虚函数指针
关于虚继承,多写一点儿
http://blog.csdn.net/xsh_123321/article/details/5956289
1.为什么需要虚继承
如下图所示如果访问Der::Fun or Der::m_nValue就会带来二义性,无法确定是调用Base1的还是Base2的,所以为了解决多重继承情况下成员访问的二义性,引入了虚继承机制。(说白了,虚继承就是共享继承,“共享”)
2.虚继承实现
在虚继承下,Der通过共享虚基类SuperBase来避免二义性,在Base1,Base2中分别保存虚基类指针,Der继承Base1,Base2,包含Base1, Base2的虚基类指针,并指向同一块内存区,这样Der便可以间接存取虚基类的成员,如下图所示:
3.不同编译器实现方式
不同编译器对间接存取的方法不同,以下以GCC和VC为例,均采用以下代码进行实验:
class SuperBase{public: int m_nValue; void Fun(){cout<<"SuperBase1"<<endl;} virtual ~SuperBase(){}};class Base1: virtual public SuperBase{public:virtual ~ Base1(){}};class Base2: virtual public SuperBase{public:virtual ~ Base2(){}};class Der:public Base1, public Base2{public:virtual ~ Der(){}};void main(){cout<<sizeof(SuperBase)<<sizeof(Base1)<<sizeof(Base2)<<sizeof(Der)<<endl;}
1) GCC中结果为8, 12, 12, 16
解析:sizeof(SuperBase) = sizeof(int) + 虚函数表指针
sizeof(Base1) = sizeof(Base2) = sizeof(int) + 虚函数指针 + 虚基类指针
sizeof(Der) = sizeof(int) + Base1中虚基类指针 + Base2虚基类指针 + 虚函数指针
GCC共享虚函数表指针,也就是说父类如果已经有虚函数表指针,那么子类中共享父类的虚函数表指针空间,不在占用额外的空间,这一点与VC不同,VC在虚继承情况下,不共享父类虚函数表指针,详见如下。
2)VC中结果为:8, 16, 16, 24
解析:sizeof(SuperBase) = sizeof(int) + 虚函数表指针
sizeof(Base1) = sizeof(Base2) = sizeof(int) + SuperBase虚函数指针 + 虚基类指针 + 自身虚函数指针
sizeof(Der) = sizeof(int) + Base1中虚基类指针 + Base2中虚基类指针 + Base1虚函数指针 + Base2虚函数指针 + 自身虚函数指针
如果去掉虚继承,结果将和GCC结果一样,A,B,C都是8,D为16,原因就是VC的编译器对于非虚继承,父类和子类是共享虚函数表指针的。
- C++-对象继承内存模型配图
- C++继承内存对象模型
- C++继承内存对象模型
- C++虚继承内存对象模型探讨
- C++虚继承内存对象模型探讨
- C++虚继承内存对象模型探讨
- C++虚继承内存对象模型探讨
- C++虚继承内存对象模型探讨
- C++虚继承内存对象模型探讨
- 虚继承内存布局@c++对象模型
- C++虚继承内存对象模型探讨
- C++-对象继承中的内存布局
- 【C++】C++对象内存模型简介
- 漫谈C++:对象内存模型分析
- 虚表结构与虚继承内存对象模型
- 虚表结构与虚继承内存对象模型
- 钻石型虚拟多重继承的C++对象内存模型
- 自己对C++虚继承内存对象模型探讨
- FontMetrics对象
- eclipse平台的设计模式
- Ftp的port模式和pasv模式
- http://blog.csdn.net/tianlesoftware
- 取得插件bundle中的文件或路径
- C++继承内存对象模型
- AbstractUIPlugin与Plugin的区别
- java程序员笔试(菜鸟必读)
- 有关插件开发中Manifest.MF和plugin.xml以及激活器的可有可无总结
- 两个整数是否同号
- JXL复制源码
- 我的FL2440怎么利用起来呢,
- 问题追踪-待续
- 使用JXL读取Excel表格,拷贝、更新Excel工作薄