当前位置: 首页 > news >正文

C++对象的内存分布和虚函数表

Linux C/C+ +开发(后端/音视频/游戏/嵌入式/高性能网络/存储/基础架构/安全)

c++中一个类中无非有四种成员:静态数据成员和非静态数据成员,静态函数和非静态函数。

1.非静态数据成员被放在每一个对象体内作为对象专有的数据成员。
2.静态数据成员被提取出来放在程序的静态数据区内,为该类所有对象共享,因此只存在一份。
3.静态和非静态成员函数最终都被提取出来放在程序的代码段中并为该类所有对象共享,因此每一个成员函数也只能存在一份代码实体。在c++中类的成员函数都是保存在静态存储区中的 ,那静态函数也是保存在静态存储区中的,他们都是在类中保存同一个惫份。

因此,构成对象本身的只有数据,任何成员函数都不隶属于任何一个对象,非静态成员函数与对象的关系就是绑定,绑定的中介就是this指针。成员函数为该类所有对象共享,不仅是处于简化语言实现、节省存储的目的,而且是为了使同类对象有一致的行为。同类对象的行为虽然一致,但是操作不同的数据成员。

#include"iostream.h"
class A
{
private:int x;int y;
public:void sety(){y=5;}void print(){cout<<"x="<<x<<endl<<"y="<<y<<endl;}
};
void main()
{A a;a.sety();a.print();int *p=(int *)&a;//对象a的内存模型里面,只有非静态数据成员,所以是合理的。*p=6;a.print();
}

4.单继承的对象的内存布局,第一个为虚函数表指针vtbl,其后为成员且先基类后子类,虚函数表里包含了所有的虚函数的地址,以NULL结束。 虚函数如果子类有重写,就由子类的重新的代替

img

添加图片注释,不超过 140 字(可选)

上述类图的解释:B的v2覆盖了A的v2,C的v1覆盖了A的v1,C的v3覆盖了B的v3.

注意:发生覆盖的特征有:

  1. 不同的范围(分别位于派生类与基类);
  2. 函数名字相同
  3. 参数相同
  4. 基类函数必须有virtual关键字

成员函数被重载的特征

(1)相同的范围(在同一个类中);
(2)函数名字相同;
(3)参数不同;
(4)virtual 关键字可有可无

隐藏”是指派生类的函数屏蔽了与其同名的基类函数,规则如下

(1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。
(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual 关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)

类C的对象的内存模型为:

img

单继承的对象的布局,第一个为虚函数表指针vtbl,其后为成员且先基类后子类,虚函数表里包含了所有的虚函数的地址,以NULL结束。虚函数如果子类有重写,就由子类的重新的代替。

5.与单继承相同的是所有的虚函数都包含在虚函数表中,所不同的多重继承有多个虚函数表,当子类对父类的虚函数有重写时,子类的函数替换父类的函数在对应的虚函数位置,当子类有新的虚函数时,这些虚函数被加在第一个虚函数表的后面

img

对类图的解释:D的v3覆盖了B3的v3,另外D有一个新的虚函数vD。

class D 的内存模型

img

总结:与单继承相同的是所有的虚函数都包含在虚函数表中,所不同的多重继承有多个虚函数表**,当子类对父类的虚函数有重写时,子类的函数覆盖父类的函数在对应的虚函数位置,当子类有新的虚函数时,这些虚函数被加在第一个虚函数表的后面**

6.虚继承,使公共的基类在子类中只有一份,我们看到虚继承在多重继承的基础上多了vbtable来存储到公共基类的偏移。

img

类图的解释:D2覆盖了B的vB,GD覆盖了D1的vD1同时也覆盖B的vB,GD也有自己的虚函数vGD。

class GD的内存模型

img

总结:虚继承,使公共的基类在子类中只有一份,我们看到虚继承在多重继承的基础上多了vbtable来存储到公共基类的偏移

整理了一些学习书籍、视频资料(Linux C++ 后端/音视频/游戏/嵌入式/高性能网络/存储/基础架构/安全
学习资料、教学视频和学习路线图),有需要的可以自行添加学习交流群:739729163 领取哦!!!

http://www.lryc.cn/news/213954.html

相关文章:

  • 小白怎么学习性能测试?一文7个知识点带你成功入门!
  • Orcad属性过滤器的使用技巧
  • 腾讯云向量数据库正式对外全量开放公测
  • Linux新建普通用户无法使用退格键与tab键
  • 【湘粤鄂车牌】
  • 华大-HC32L130F8UA 内存使用注意事项
  • 怎样才知道一个单片机的性能到极限了?
  • Android Studio的笔记--SerialPort串口通讯学习和使用
  • MySQL 启动选项和字符集
  • 社区投稿|解码Big Vector,开启Sui超扩展性的新篇章
  • Linux根目录下的目录结构及其作用详解
  • 源码和SaaS账号:租房与自建房的区别
  • Docker容器设置为自动重启
  • 速卖通卖家如何通过自己搭建测评补单系统,提高产品权重和排名?
  • 香港金融科技周2023:AIGC重塑金融形态
  • 6G关键新兴技术-智能超表面(RIS)技术演进
  • 怎么让小程序排名靠前?小程序搜索排名问题
  • 使用Postman快速复现浏览器的请求(包括生成调用代码)
  • 四则运算的正则校验
  • 【备忘录】SpringBoot+ dynamic-datasource配置自定义多数据源
  • 制作docker镜像文件
  • JAVA 中 Socket 和 WebSocket 区别
  • python 接收到一个接口的数据 是json格式 ,然后把其中键值对的一个值改掉 再返回给接口
  • ⌈C++11⌋实现一个简易计算器
  • 面试算法45:二叉树最低层最左边的值
  • Could not find org.jetbrains.kotlin:kotlin-stdlib-jre7:1.5.21.
  • LoRaWan之LoRaMAC 的快速入门指南
  • 中国教育企业出海 新兴技术助力抢占先机
  • IntelliJ IDEA2023旗舰版和社区版下载安装教程(图解)
  • 【RxJava】map过程中各个Observable生命周期分析