C++ 虚函数和多重继承的内存布局初探
C++ 对象的内存布局
一切以事实说话:
代码:
1: #include <stdio.h>
2:
3: class A {
4: public:
5: int a;
6: int b;
7: int c;
8: };
9:
10: int main(int argc, char** argv) {
11: A obj;
12: printf(" obj :%p\n obj.a: %p \n obj.b: %p \n obj.c: %p\n" ,
13: &obj, &obj.a, &obj.b, &obj.c);
14: return 0;
15: }
执行结果:

不同的机器执行的结果可能不同,但是从这里的出的一个结论是:
对象的地址是整个类的起始地址(也就是低地址)。其成员的地址顺序和其在类中声明的顺序有关系。
而对上面的代码稍加修改,增加一个虚函数。
1: #include <stdio.h>
2:
3: class A {
4: public:
5: virtual void show() {}
6: int a;
7: int b;
8: int c;
9: };
10:
11: int main(int argc, char** argv) {
12: A obj;
13: printf(" obj :%p\n obj.a: %p \n obj.b: %p \n obj.c: %p\n" ,
14: &obj, &obj.a, &obj.b, &obj.c);
15: return 0;
16: }
测试结果:

这里是由于增加了一个虚函数表的指针(测试机器为64位系统,故指针为8个字节)。从这里可以看出,虚函数表指针在类的起始地址,这也是为了对于不同的类该地址的偏移相同。
1: class X {
2: };
3: class Y {
4: public:
5: virtual void f() {};
6: };
7: class X1 : public virtual X {
8: };
9: class X2 : public virtual X {
10: };
11: class A1 : public X1, public X2 {
12: };
13: class X3 : public X {
14: };
15: class X4 : public X {
16: };
17: class A2 : public X3, public X4 {
18: };
19: class Y1 : public virtual Y {
20: };
21: class Y2 : public virtual Y {
22: };
23: class B1 : public Y1, public Y2 {
24: };
25: class Y3 : public Y {
26: };
27: class Y4 : public Y {
28: };
29: class B2 : public Y3, public Y4 {
30: };
31:
32: int main (int argc, char** argv) {
33: printf("sizeof(X) %lu\n", sizeof(X));
34: printf("sizeof(Y) %lu\n", sizeof(Y));
35: printf("sizeof(X1) %lu\n", sizeof(X1));
36: printf("sizeof(X2) %lu\n", sizeof(X2));
37: printf("sizeof(A1) %lu\n", sizeof(A1));
38: printf("sizeof(X3) %lu\n", sizeof(X3));
39: printf("sizeof(X4) %lu\n", sizeof(X4));
40: printf("sizeof(A2) %lu\n", sizeof(A2));
41: printf("sizeof(Y1) %lu\n", sizeof(Y1));
42: printf("sizeof(Y2) %lu\n", sizeof(Y2));
43: printf("sizeof(B1) %lu\n", sizeof(B1));
44: printf("sizeof(Y3) %lu\n", sizeof(Y3));
45: printf("sizeof(Y4) %lu\n", sizeof(Y4));
46: printf("sizeof(B2) %lu\n", sizeof(B2));
47: return 0;
48: }
执行结果:

上面的测试结果得出的结论:
- 空类的大小不是0,而是1,这样是提供一个占位符,这样由空类创建出的两个对象的地址就会不同,以作区分。
- 当类不是空的时候,该占位符就不需要了,类的大小就是类中成员所需的空间大小
注: 本想深入一探究竟,不过这部分和编译器有很大的关系,非朝夕可以搞定。先写这么多,再多做了解后再补充吧。
refer:
http://blog.csdn.net/haoel/article/details/3081328
http://blog.csdn.net/haoel/article/details/3081385
http://blog.chinaunix.net/uid-22535463-id-2749544.html
C++ 虚函数和多重继承的内存布局初探的更多相关文章
- vs查看虚函数表和类内存布局
虚继承和虚基类 虚继承:在继承定义中包含了virtual关键字的继承关系: 虚基类:在虚继承体系中的通过virtual继承而来的基类,需要注意的是:class CSubClass : publ ...
- 如何使用C#调用C++类虚函数(即动态内存调用)
本文讲解如何使用C#调用只有.h头文件的c++类的虚函数(非实例函数,因为非虚函数不存在于虚函数表,无法通过类对象偏移计算地址,除非用export导出,而gcc默认是全部导出实例函数,这也是为什么 ...
- C++中虚函数继承类的内存占用大小计算
计算一个类对象的大小时的规律: 1.空类.单一继承的空类.多重继承的空类所占空间大小为:1(字节,下同): 2.一个类中,虚函数本身.成员函数(包括静态与非静态)和静态数据成员都是不占用类对象的存储空 ...
- 从零开始学C++之虚继承和虚函数对C++对象内存模型造成的影响
首先重新回顾一下关于类/对象大小的计算原则: 类大小计算遵循结构体对齐原则 第一个数据成员放在offset为0的位置 其它成员对齐至min(sizeof(member),#pragma pack(n) ...
- Vc++内存布局
Vc++内存布局 测试平台 Windows server 2012 R2 and visual studio 2013 professional. 本篇文章意在介绍vc++中类的内存布局方式,只是研究 ...
- HotSpot源码分析之C++对象的内存布局
HotSpot采用了OOP-Klass模型来描述Java类和对象.OOP(Ordinary Object Pointer)指的是普通对象指针,而Klass用来描述对象的具体类型.为了更好理解这个模型, ...
- c++ 对象内存分配和虚函数
1. c++类对象(不含虚函数)在内存中的分布 c++类中有四种成员:静态数据.非静态数据.静态函数.非静态函数. 1. 非静态数据成员放在每个对象内部,作为对象专有的数据成员 2. 静态数据成员被抽 ...
- 浅析GCC下C++多重继承 & 虚拟继承的对象内存布局
继承是C++作为OOD程序设计语言的三大特征(封装,继承,多态)之一,单一非多态继承是比较好理解的,本文主要讲解GCC环境下的多重继承和虚拟继承的对象内存布局. 一.多重继承 先看几个类的定义: 01 ...
- 虚函数列表: 取出方法 // 虚函数工作原理和(虚)继承类的内存占用大小计算 32位机器上 sizeof(void *) // 4byte
#include <iostream> using namespace std; class A { public: A(){} virtual void geta(){ cout < ...
随机推荐
- java 静态内存图、静态代码块
package java08; /* 静态代码块格式: public class 类名称{ static{ //静态代码块 } } 特点:当第一次执行本类时,静态代码块执行唯一的一次 * */ pub ...
- Java字节数组流学习
字节数组流 基于内存操作,内部维护着一个字节数组,我们可以利用流的读取机制来处理字符串.无需关闭,不会报IOException. ByteArrayInputStream 包含一个内部缓冲区,该缓冲区 ...
- 爬虫技术:cookies池的维护
一:为什么要维护cookie 1.登录才能爬取内容 2.爬取频繁会被封号. 3.需要维护多个账号的cookie,实现大规模抓取 二:cookies的要求 1.自动登录更新 2.定期筛选验证 3.提供外 ...
- spring微服务(顺序由简入难易于理解)
一.为微服务应用增加健康监控 1.在 build.gradle 文件 dependencies 属性中增加 compile('org.springframework.boot:spring-boot- ...
- Spring Security 安全认证
Spring Boot 使用 Mybatis 依赖 <dependency> <groupId>org.mybatis.spring.boot</groupId> ...
- Monkey命令及调试
monkey命令: 执行50w次,随机数200,忽略crash,忽略超时,详细信息级别为1:monkey -p 包名 -s 200 --throttle 100 --ignore-crashes -- ...
- loadrunner(预测系统行为和性能的负载测试工具)
LoadRunner,是一种预测系统行为和性能的负载测试工具.通过以模拟上千万用户实施并发负载及实时性能监测的方式来确认和查找问题,LoadRunner能够对整个企业架构进行测试.企业使用LoadRu ...
- bugku | flagphp
1.开脑洞 http://123.206.87.240:8002/flagphp/?hint=1 2.读源码得到条件是要求反序列化后的‘ISecer’的值等于$KEY <?php error_r ...
- 杂项-报表-Minitab:Minitab百科
ylbtech-杂项-报表-Minitab:Minitab百科 Minitab软件是现代质量管理统计的领先者,全球六西格玛实施的共同语言,以无可比拟的强大功能和简易的可视化操作深受广大质量学者和统计专 ...
- English-such as, for example, include and contain
such as 后接动词,通常用动名词,有时也可用动词原形 for example 后接动词,用动名词 include vt. 包含,包括 后接动词,用动名词 英英: If one thing inc ...