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

  一、父类子类都为空

#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. hadoop+hbase

    hadoop的配置见下面这篇文章 http://www.powerxing.com/install-hadoop-2-4-1-single-node/ Hadoop安装教程_单机/伪分布式配置_Had ...

  2. POJ 1060 Modular multiplication of polynomials(多项式的加减乘除,除法转化成减法来求)

    题意:给出f(x),g(x),h(x)的 (最高次幂+1)的值,以及它们的各项系数,求f(x)*g(x)/h(x)的余数. 这里多项式的系数只有1或0,因为题目要求:这里多项式的加减法是将系数相加/减 ...

  3. POJ2251Dungeon Master

    http://poj.org/problem?id=2251 题意 : 就是迷宫升级版,从以前的一个矩阵也就是一层,变为现在的L层," . "是可以走,但是“#”不可以走,从S走到 ...

  4. ibatis框架文件配置

    最近2天在学ibatis,心里也有一些心得,就把它写下来了. 首先是配置一下ibatis的环境,添加ibatis2.X.jar,mysql-connection-bin.5.1.8.jar,建立一个w ...

  5. LR_问题_无法使用LR的Controller,提示缺少license

    问题描述 无法使用LR的Controller,提示缺少license 问题解决 使用开始->所有程序->HP LoadRunner->loadrunner,在打开界面的左上角选择co ...

  6. 百度网盘,前几天刚从百度云改名过来,百度云这个名字给之前的百度开放云(同步盘用户比较小众)good

    作者:黑郁金香链接:http://www.zhihu.com/question/51803053/answer/127562835来源:知乎著作权归作者所有,转载请联系作者获得授权. 在8月网盘大面积 ...

  7. JCIFS是很不稳定的

    我以前也试过这样登录失败,第二天就能登录成功了. JCIFS是很不稳定的. 如果是域登录可以这样 //DOMAIN_IP         域名服务(其实域名和域名服务器IP可以,不过用IP解析速度快很 ...

  8. 【c】time.h

    表示时间的三种类型 日历时间:从一个时间点到现在的秒数,用time_t表示 始终滴答时间:从进程启动到现在时钟的滴答数(每秒一般包含1000个).用clock_t表示 分解时间:分解的数据结构如下.用 ...

  9. python - PipeMapRed.waitOutputThreads(): subprocess failed with code 1

    hadoop上执行mapreduce streaming python程序报错, 报错详细信息为 python - PipeMapRed.waitOutputThreads(): subprocess ...

  10. javadoc 和 javadoc注释规范

    javadoc是Sun公司提供的一个技术,它从程序源代码中抽取类.方法.成员等注释形成一个和源代码配套的API帮助文档. javadoc命令是用来生成自己API文档的,使用方式:在dos中在目标文件所 ...