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

  一、父类子类都为空

#include <cstdio>

class A
{ }; class B: public A
{ }; int main(int argc, char** argv)
{
printf("%d\n", sizeof(B));
}

  windows输出:

1

  和一个空类时情况一致。

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

#include <cstdio>

class A
{
public:
int a;
}; class B: public A
{ }; class AA
{ }; class BB: public AA
{
public:
int b;
}; class AAA
{
public:
int a;
}; class BBB: public AAA
{
public:
int b;
}; int main(int argc, char** argv)
{
printf("%d\n", sizeof(B));
printf("%d\n", sizeof(BB));
printf("%d\n", sizeof(BBB));
}

  windows输出:

4
4
8

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

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

#include <cstdio>

class A
{
public:
int a;
virtual void vfun(){};
}; class B: public A
{ }; int main(int argc, char** argv)
{
printf("%d\n", sizeof(B)); B b;
b.a = 0xaaaaaaaa;
B* pb = &b;
printf("%08x\n", pb);
}

  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的虚函数。

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

#include <cstdio>

class A
{
public:
int a;
virtual void vfun(){};
}; class B: public A
{
public:
void vfun(){};
}; int main(int argc, char** argv)
{
printf("%d\n", sizeof(B)); B b;
b.a = 0xaaaaaaaa;
B* pb = &b;
printf("%08x\n", pb);
}

  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中的实现。

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

#include <cstdio>

class A
{
public:
int a;
}; class B: virtual public A
{
public:
}; int main(int argc, char** argv)
{
printf("%d\n", sizeof(B)); B b;
b.a = 0xaaaaaaaa;
B* pb = &b;
printf("%08x\n", pb);
}

  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

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

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

#include <cstdio>

class A
{
public:
int a;
virtual void vfun(){};
}; class B: virtual public A
{
public:
}; int main(int argc, char** argv)
{
printf("%d\n", sizeof(B)); B b;
b.a = 0xaaaaaaaa;
B* pb = &b;
printf("%08x\n", pb);
}

  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. leetcode Triangle及其思考

    Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent n ...

  2. python库:fuzzywuzzy

    fuzzywuzzy 用于字符串匹配率.令牌匹配等 复制代码代码如下: from fuzzywuzzy import fuzzfuzz.ratio("Hit me with your bes ...

  3. 【hadoop2.6.0】一句话形容mapreduce

    网上看到的: We want to count all the books in the library. You count up shelf #1, I count up shelf #2. Th ...

  4. call,apply,bind方法的总结

    why?call,apply,bind干什么的?为什么要学这个? 一般用来指定this的环境,在没有学之前,通常会有这些问题. var a = { user:"追梦子", fn:f ...

  5. hdu 1270 小希的数表

    思路:一定有sum[1]=num[1]+num[2],sum[2]=num[1]+num[3]; 但是sum[3]不知道是由num[1]+num[4]还是num[2]+num[3],这就需要枚举一下了 ...

  6. P1011 传纸条//dp优化改进状态表示

    P1011 传纸条 时间: 1000ms / 空间: 131072KiB / Java类名: Main 背景 NOIP2008复赛提高组第三题 描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不 ...

  7. THUSC 2016游记

    又去北京转了一圈,拿到了很不错的协议,非常的开森 day -1 6.2 上午去pku的同学就走了QAQ 然后波哥说下午要考试,考联考题 我一脸无奈的表示我已经提前要到题目而且看了题了 然后波哥就决定给 ...

  8. Compare_Connect_Letter

    题目描述: 比较两个数字mn和nm(如果mn<nm则m<n, 如果nm<mn则n<m,否则n=m) 连接这两个数字 如(mnnm) //比较两个数字mn和nm(如果mn< ...

  9. 【mongoDB运维篇④】Shard 分片集群

    简述 为何要分片 减少单机请求数,降低单机负载,提高总负载 减少单机的存储空间,提高总存空间. 常见的mongodb sharding 服务器架构 要构建一个 MongoDB Sharding Clu ...

  10. swift学习笔记-UI篇之UIImageView

    1.基本使用 将要使用的图片拖入到项目里,我这里使用的是名为“1.jpg”的图片,然后创建UIImageView,并设置要显示的图片为"1.jpg"//1. 基本使用 let im ...