【c++内存分布系列】单继承

时间:2023-01-14 10:13:34

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

  一、父类子类都为空

#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&plus;&plus;继承 派生类中的内存布局(单继承、多继承、虚拟继承)

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

  2. C&plus;&plus;对象内存分布&lpar;3&rpar; - 菱形继承&lpar;virtual&rpar;

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

  3. 【c&plus;&plus;内存分布系列】虚基类表

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

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

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

  5. 【C&plus;&plus; Primer &vert; 15】C&plus;&plus;类内存分布

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

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

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

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

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

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

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

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

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

随机推荐

  1. 29 个 PHP 的 Excel 处理类

    下面的 PHP Excel 处理类中,包含 Excel 读写.导入导出等相关的类,列表如下: PHP Excel Reader classes 1. Read Excel Spreadsheets u ...

  2. yum install错误 系统环境:Oracle Linux5&period;4 在通过yum安装软件时出现以下错误:

    1.yum配置文件 1 [root@rh168 yum.repos.d]# cat yum.repo  2 [base] 3 name=Oracle linux  4 baseurl=file:/// ...

  3. Linux平台下Java调用C函数

    JNI是Java native interface的简写,可以译作Java原生接口.Java可以通过JNI调用C/C++的库,这对于那些对性能要求比较高的Java程序无疑是一个 福音. 使用JNI也是 ...

  4. HTML与CSS入门——第五章 使用文本块和列表

    知识点: 1.在页面上对齐文本的方法 2.三种HTML列表的使用方法 3.在列表中放置列表的方法 5.1 在页面上对齐文本: 父元素内子元素文本的居中:在控制父元素的text-align:center ...

  5. 44&period; leetcode 28&period; Implement strStr&lpar;&rpar;

    28. Implement strStr() Implement strStr(). Returns the index of the first occurrence of needle in ha ...

  6. OTP&amp&semi;ETS

    最近觉得实在是该梳理梳理erlang的框架内容了,所以整理了下. OTP(开放电信平台):并发系统平台, 特点:容错(erlang:get_stacktrace(),try-catch,trap_ex ...

  7. ThinkPHP3&period;2 中空方法、空控制器和空模块的设置

    ThinkPHP3.2 中空方法.空控制器和空模块的设置 1.空方法设置 问题: 当你访问一个不存在的方法的时候: 如: http://localhost/test/index.php/Home/Us ...

  8. Git clone、git reset

    一,git clone 1,git clone某一个分支 git clone -b <branch> <remote_repo> 2,.git 文件太大 :clone的时候,可 ...

  9. vue中请求本地的json数据

    为什么要请求本地的数据?模拟后台的请求数据,验证页面的逻辑是否存在问题,抛开后台提前开发等. 常用的说来有:jq的方式 约等于 axios的方式,vuex状态管理的方式 个人认为最好用的就是jq的方式 ...

  10. Distinct Subsequences leetcode java

    题目: Given a string S and a string T, count the number of distinct subsequences of T in S. A subseque ...