父类包括成员函数、静态函数、静态方法,子类包括成员函数、静态函数、静态方法的情况与一个类时完全一致,这里就不做分析了。子类单独包含虚函数时继承无关,也不做分析了。

  一、父类子类都为空

  1. #include <cstdio>
  2.  
  3. class A
  4. {
  5.  
  6. };
  7.  
  8. class B: public A
  9. {
  10.  
  11. };
  12.  
  13. int main(int argc, char** argv)
  14. {
  15. printf("%d\n", sizeof(B));
  16. }

  windows输出:

1

  和一个空类时情况一致。

  二、父类包含成员变量、子类包含成员变量或子类父类都包含成员变量

  1. #include <cstdio>
  2.  
  3. class A
  4. {
  5. public:
  6. int a;
  7. };
  8.  
  9. class B: public A
  10. {
  11.  
  12. };
  13.  
  14. class AA
  15. {
  16.  
  17. };
  18.  
  19. class BB: public AA
  20. {
  21. public:
  22. int b;
  23. };
  24.  
  25. class AAA
  26. {
  27. public:
  28. int a;
  29. };
  30.  
  31. class BBB: public AAA
  32. {
  33. public:
  34. int b;
  35. };
  36.  
  37. int main(int argc, char** argv)
  38. {
  39. printf("%d\n", sizeof(B));
  40. printf("%d\n", sizeof(BB));
  41. printf("%d\n", sizeof(BBB));
  42. }

  windows输出:

4
4
8

  内存为成员变量,包括父类的。

  三、父类包含虚函数,子类未实现该函数

  1. #include <cstdio>
  2.  
  3. class A
  4. {
  5. public:
  6. int a;
  7. virtual void vfun(){};
  8. };
  9.  
  10. class B: public A
  11. {
  12.  
  13. };
  14.  
  15. int main(int argc, char** argv)
  16. {
  17. printf("%d\n", sizeof(B));
  18.  
  19. B b;
  20. b.a = 0xaaaaaaaa;
  21. B* pb = &b;
  22. printf("%08x\n", pb);
  23. }

  windows输出:

8
003ffe40

  查看对象b的内存:

003FFE40 4C
003FFE41 57
003FFE42 22 00
003FFE44 AA
003FFE45 AA
003FFE46 AA
003FFE47 AA

  查看虚表0x0022574c:

B::`vftable':
0022574C 22 11 
0022574E 22 00 
00225750 00 00 
00225752 00 00

  查看虚表指向的地址:

A::vfun:
00221122 E9 19 04 00 00 jmp A::vfun (221540h)

7: virtual void vfun(){};
00221540 55 push ebp
00221541 8B EC mov ebp,esp
00221543 81 EC CC 00 00 00 sub esp,0CCh

  可知b.vfun()执行的是a的虚函数。

  四、父类包含虚函数、子类实现该函数

  1. #include <cstdio>
  2.  
  3. class A
  4. {
  5. public:
  6. int a;
  7. virtual void vfun(){};
  8. };
  9.  
  10. class B: public A
  11. {
  12. public:
  13. void vfun(){};
  14. };
  15.  
  16. int main(int argc, char** argv)
  17. {
  18. printf("%d\n", sizeof(B));
  19.  
  20. B b;
  21. b.a = 0xaaaaaaaa;
  22. B* pb = &b;
  23. printf("%08x\n", pb);
  24. }

  windows输出:

8
002bfc10

  查看对象b地址内容:

002BFC10 4C
002BFC11 57
002BFC12 E7 00
002BFC14 AA
002BFC15 AA
002BFC16 AA
002BFC17 AA

  查看虚表0x00e7574c:

B::`vftable':
00E7574C 27  
00E7574D 11 E7  
00E7574F 00 00

  查看该续表中的指针0x00e71127:

B::vfun:
00E71127 E9 24 04 00 00 jmp B::vfun (0E71550h)

10: class B: public A
11: {
12: public:
13: void vfun(){};
00E71550 55 push ebp
00E71551 8B EC mov ebp,esp
00E71553 81 EC CC 00 00 00 sub esp,0CCh

  可知该虚表指向类B中的实现。

  五、虚继承父类,子类为空

  1. #include <cstdio>
  2.  
  3. class A
  4. {
  5. public:
  6. int a;
  7. };
  8.  
  9. class B: virtual public A
  10. {
  11. public:
  12. };
  13.  
  14. int main(int argc, char** argv)
  15. {
  16. printf("%d\n", sizeof(B));
  17.  
  18. B b;
  19. b.a = 0xaaaaaaaa;
  20. B* pb = &b;
  21. printf("%08x\n", pb);
  22. }

  windows输出:

8
0036f810

  查看对象b内存:

0036F810 48
0036F811 57
0036F812 34 01
0036F814 AA
0036F815 AA
0036F816 AA
0036F817 AA

  内存中多了0x01345748,这个是虚基类表的指针,作用于虚函数表类似后面会详细讲。查看该虚基类表:

B::`vbtable':
01345748 00 00
0134574A 00 00
0134574c 04 00
0134574e 00 00

  虚基类表内容含义后面讲。

  六、虚继承父类包含虚函数

  1. #include <cstdio>
  2.  
  3. class A
  4. {
  5. public:
  6. int a;
  7. virtual void vfun(){};
  8. };
  9.  
  10. class B: virtual public A
  11. {
  12. public:
  13. };
  14.  
  15. int main(int argc, char** argv)
  16. {
  17. printf("%d\n", sizeof(B));
  18.  
  19. B b;
  20. b.a = 0xaaaaaaaa;
  21. B* pb = &b;
  22. printf("%08x\n", pb);
  23. }

  windows输出:

12
002efa64

  可见内存又增加了4字节。看下对象b内存:

002EFA64 54
002EFA65 57
002EFA66 86 00
002EFA68 4C
002EFA69 57
002EFA6A 86 00
002EFA6C AA
002EFA6D AA
002EFA6E AA
002EFA6F AA

  有两个指针,分别为虚基类表和虚函数表:

B::`vftable':
0086574C 22 11
0086574E 86 00
00865750 00 00
00865752 00 00
B::`vbtable':
00865754 00 00
00865756 00 00

  此例中子类未实现虚函数。子类实现虚函数与四类似,只是这里多了个虚基类表,就不详细讲了。

【c++内存分布系列】单继承的更多相关文章

  1. C++继承 派生类中的内存布局(单继承、多继承、虚拟继承)

    今天在网上看到了一篇写得非常好的文章,是有关c++类继承内存布局的.看了之后获益良多,现在转在我自己的博客里面,作为以后复习之用. ——谈VC++对象模型(美)简.格雷程化    译 译者前言 一个C ...

  2. C++对象内存分布(3) - 菱形继承(virtual)

    1.前言 本篇文章的全部代码样例.假设是windows上编译执行.则使用的是visual studio 2013.假设是RHEL6.5平台(linux kernal: 2.6.32-431.el6.i ...

  3. 【c++内存分布系列】虚基类表

    虚基类表相对于虚函数表要稍微难理解些,故单独提出来. 虚函数表是在对象生成时插入一个虚函数指针,指向虚函数表,这个表中所列就是虚函数. 虚基类表原理与虚函数表类似,不过虚基类表的内容有所不同.表的第一 ...

  4. 【c++内存分布系列】单独一个类

    首先要明确类型本身是没有具体地址的,它是为了给编译器生成相应对象提供依据.只有编译器生成的对象才有明确的地址. 一.空类 形如下面的类A,类里没有任何成员变量,类的sizeof值为1. #includ ...

  5. 【C++ Primer | 15】C++类内存分布

    C++类内存分布 书上类继承相关章节到这里就结束了,这里不妨说下C++内存分布结构,我们来看看编译器是怎么处理类成员内存分布的,特别是在继承.虚函数存在的情况下. 下面可以定义一个类,像下面这样: c ...

  6. C++类虚函数内存分布(这个 你必须懂)

    转自:http://www.cnblogs.com/jerry19880126/p/3616999.html C++类内存分布 书上类继承相关章节到这里就结束了,这里不妨说下C++内存分布结构,我们来 ...

  7. C++中继承 声明基类析构函数为虚函数作用,单继承和多继承关系的内存分布

    1,基类析构函数不为虚函数 #include "pch.h" #include <iostream> class CBase { public: CBase() { m ...

  8. c++内存分布之虚函数(单一继承)

    系列 c++内存分布之虚函数(单一继承) [本文] c++内存分布之虚函数(多继承) 结论 1.虚函数表指针 和 虚函数表 1.1 影响虚函数表指针个数的因素只和派生类的父类个数有关.多一个父类,派生 ...

  9. c++内存分布之虚函数(多继承)

    系列 c++内存分布之虚函数(单一继承) c++内存分布之虚函数(多继承) [本文] 结论 1.虚函数表指针 和 虚函数表 1.1 影响虚函数表指针个数的因素只和派生类的父类个数有关.多一个父类,派生 ...

随机推荐

  1. StringBuffer用法

    public class StringBufferTest { public static void main(String[] args) { StringBuffer sb=new StringB ...

  2. Android 监测手机联网状态 wifi、移动数据流量、无联网状态

    手机当完成联网时会发送一个广播,我们只要创建一个广播接收者即可,代码如下: package com.example.NetworkChangeReceiver2; import android.con ...

  3. Python新式类和旧式类的区别

    新式类是为了统一**而在2.2中开始引入的. 代码讲解 上面的例子比较明白的说明了问题. B是定义的新式类.那么输入b的时候,不论是type(b),还是b.__class__都是输出的<clas ...

  4. Oracle 10 - 数据库表

    Oracle数据库表类型 1.堆表 2.索引组织表 3.索引clustered表 4.散列clustered表 5.有序散列clustered表 6.嵌套表 7.临时表 8.对象表 9.外部表 Ora ...

  5. cvc-elt.1: Cannot find the declaration of element---与spring 无关的schema 验证失败

    晚上查了好久,都是spring 出这种问题的解决方式,终于查到为什么了. http://wakan.blog.51cto.com/59583/7218/ 转自这个人.. 多谢啦! 为了验证 XML 文 ...

  6. CF 353C Find Maximum #205 (Div. 2)

    #include<stdio.h> #include<string.h> #include<algorithm> using namespace std; ]; ] ...

  7. SpringMVC学习总结(五)——SpringMVC文件上传例子

    这是用的是SpringMVC-3.1.1.commons-fileupload-1.2.2和io-2.0.1 首先是web.xml <?xml version="1.0" e ...

  8. Filter高级开发

    孤傲苍狼 只为成功找方法,不为失败找借口! javaweb学习总结(四十三)——Filter高级开发 在filter中可以得到代表用户请求和响应的request.response对象,因此在编程中可以 ...

  9. Nginx安装部署

    Nginx ("engine x") 是一个高性能的 HTTP 和 反向代理 服务器,也是一个 IMAP/POP3/SMTP 代理服务器. Nginx 是由 Igor Sysoev ...

  10. hadoop拾遗(一)---- 避免切分map文件

    有些程序可能不希望文件被切分,而是用一个mapper完整处理每一个输入文件.例如,检查一个文件中所有记录是否有序,一个简单的方法是顺序扫描第一条记录并并比较后一条记录是否比前一条要小.如果将它实现为一 ...