【c++内存分布系列】单继承
父类包括成员函数、静态函数、静态方法,子类包括成员函数、静态函数、静态方法的情况与一个类时完全一致,这里就不做分析了。子类单独包含虚函数时继承无关,也不做分析了。
一、父类子类都为空
#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++内存分布系列】单继承的更多相关文章
- C++继承 派生类中的内存布局(单继承、多继承、虚拟继承)
今天在网上看到了一篇写得非常好的文章,是有关c++类继承内存布局的.看了之后获益良多,现在转在我自己的博客里面,作为以后复习之用. ——谈VC++对象模型(美)简.格雷程化 译 译者前言 一个C ...
- C++对象内存分布(3) - 菱形继承(virtual)
1.前言 本篇文章的全部代码样例.假设是windows上编译执行.则使用的是visual studio 2013.假设是RHEL6.5平台(linux kernal: 2.6.32-431.el6.i ...
- 【c++内存分布系列】虚基类表
虚基类表相对于虚函数表要稍微难理解些,故单独提出来. 虚函数表是在对象生成时插入一个虚函数指针,指向虚函数表,这个表中所列就是虚函数. 虚基类表原理与虚函数表类似,不过虚基类表的内容有所不同.表的第一 ...
- 【c++内存分布系列】单独一个类
首先要明确类型本身是没有具体地址的,它是为了给编译器生成相应对象提供依据.只有编译器生成的对象才有明确的地址. 一.空类 形如下面的类A,类里没有任何成员变量,类的sizeof值为1. #includ ...
- 【C++ Primer | 15】C++类内存分布
C++类内存分布 书上类继承相关章节到这里就结束了,这里不妨说下C++内存分布结构,我们来看看编译器是怎么处理类成员内存分布的,特别是在继承.虚函数存在的情况下. 下面可以定义一个类,像下面这样: c ...
- C++类虚函数内存分布(这个 你必须懂)
转自:http://www.cnblogs.com/jerry19880126/p/3616999.html C++类内存分布 书上类继承相关章节到这里就结束了,这里不妨说下C++内存分布结构,我们来 ...
- C++中继承 声明基类析构函数为虚函数作用,单继承和多继承关系的内存分布
1,基类析构函数不为虚函数 #include "pch.h" #include <iostream> class CBase { public: CBase() { m ...
- c++内存分布之虚函数(单一继承)
系列 c++内存分布之虚函数(单一继承) [本文] c++内存分布之虚函数(多继承) 结论 1.虚函数表指针 和 虚函数表 1.1 影响虚函数表指针个数的因素只和派生类的父类个数有关.多一个父类,派生 ...
- c++内存分布之虚函数(多继承)
系列 c++内存分布之虚函数(单一继承) c++内存分布之虚函数(多继承) [本文] 结论 1.虚函数表指针 和 虚函数表 1.1 影响虚函数表指针个数的因素只和派生类的父类个数有关.多一个父类,派生 ...
随机推荐
- Struts 2知识回顾----拦截器(Intercept)总结
什么是Struts 2拦截器? 从软件构架上来说,拦截器是实现了面向方面编程的组件.它将影响了多个业务对象的公共行为封装到一个个可重用的模块,减少了系统的重复代码,实现功能的高度内聚,确保了业务对象的 ...
- java基础知识回顾之java Thread类学习(十)--线程的状态以及转化使用的方法介绍
线程的概述: 线程是程序的多个执行路径,执行调度的单位,依托于进程存在.线程不仅可以共享进程的内存,而且还拥有一个属于自己的内存空间,这段内存空间叫做线程栈,是建立线程的时候由系 ...
- hdu 1275 两车追及或相遇问题
思路:这里有2种情况: 一种是相遇:满足关系是 (va+vb)*t=L*(2*n-1) 一种是追及: 满足关系是 |va-vb|*t=L*(2*n-1) 这样求出2种情况的时间,在排序就可以了…… 链 ...
- 分享一个安装PE到硬盘的软件
Ton8pe_v5.0下载地址:http://pan.baidu.com/share/link?shareid=424350&uk=4180312589 电脑是XP,有光驱,但是没win8.1 ...
- lintcode:最大子正方形
题目: Maximal Square Given a 2D binary matrix filled with 0's and 1's, find the largest square contain ...
- lintcode:Length of Last Word 最后一个单词的长度
题目: 最后一个单词的长度 给定一个字符串, 包含大小写字母.空格' ',请返回其最后一个单词的长度. 如果不存在最后一个单词,请返回 0 . 样例 给定 s = "Hello World& ...
- *[codility]MaxDoubleSliceSum
https://codility.com/demo/take-sample-test/max_double_slice_sum 两个最大子段和相拼接,从前和从后都扫一遍.注意其中一段可以为0.还有最后 ...
- 关于use-default-filters的一个问题
use-default-filters=true 默认行为会自动扫描所有注解
- sqlplus时报Linux-x86_64 Error: 13: Permission denied
在本机上非oracle用户运行sqlplus时,报以下错误:[cpdds@node1 ~]$ sqlplus cpdds_pdata/cpdds_pdata SQL*Plus: Release 10. ...
- 在Tomcat中配置数据源
使用工具:TOMCAT 7.0.52.IntelliJ IDEA 13.0.2.JSF 2.0+.SqlServer.jtds-1.2.5.jar 搞了好久都没成功,开始使用注解引入DataSourc ...