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

C++对象模型

C++对象模型是C++语言中关于对象如何在内存中布局和如何工作的底层机制。理解C++对象模型对于编写高效、正确的C++代码非常重要。

基本概念

  1. 对象内存布局:C++对象在内存中的组织方式

  2. 虚函数机制:实现运行时多态的基础

  3. 继承模型:单继承、多继承和虚继承的实现

  4. 成员访问:成员变量和成员函数的访问机制

不含有有虚函数的对象模型

对于不包含虚函数的简单类:

内存布局:

  • 成员变量按声明顺序排列

  • 成员函数不占用对象空间(存储在代码区)

 空类的大小:

  • 如果一个类没有任何数据成员(包括静态成员),它的大小通常是 1字节(具体取决于编译器和内存对齐规则)。

带有虚函数的对象模型

当类包含虚函数时,编译器会添加一个虚函数表指针(vptr):

内存布局:

  1. 虚表指针(vptr)指向虚函数表(vtable)

  2. 然后是成员变量

  3. 虚函数表中存储着虚函数地址

 

继承模型

单继承

 1、对一般继承而言,若子类重写(overwrite)了父类的虚函数,则子类虚函数将覆盖虚表中对应的父类虚函数(注意子类与父类拥有各自的一个虚函数表);

2、若子类并无overwrite父类虚函数,而是声明了自己新的虚函数,则该虚函数地址将扩充到虚函数表最后。

3、而对于虚继承,若子类overwrite父类虚函数,同样地将覆盖父类子物体中的虚函数表对应位置,而若子类声明了自己新的虚函数,则编译器将为子类增加一个新的虚表指针vptr,这与一般继承不同。

多继承 

1、一般多继承 (非菱形继承)

        如果继承于多个基类,且这个多个基类中有虚函数,那么 这个类 会有多个虚函数表。

这个类的对象会有多个虚函数表指针。

         子类的虚函数被放在声明的第一个基类的虚函数表中。

        overwrite时,所有基类的同名虚函数都被子类的同名虚函数覆盖。这样做就是为了解决不同的基类类型的指针指向同一个子类实例,而能够调用到实际的函数。

        内存布局中,父类按照其声明顺序排列。

2、菱形继承
class A { int data; };
class B : public A { int b_data; };
class C :public A { int c_data; };
class D :public B, public c { int d_data; };

 

 问题:D的对象会包含两份 A 的成员。通过D 访问A 的成员 data 会编译错误,需要通过 B::data 或 C::data 明确路径。

内存布局

 

         相较于一般多继承,公共继承类在两个虚表中都有。

3.虚继承
class A { int data; };
class B : virtual public A { int b_data; };
class C : virtual  public A { int c_data; };
class D : public B, public c { int d_data; };

 最终派生类负责构造虚基类
注意:在虚继承的情况下,虚基类的构造由最底层的派生类直接负责,而不是由中间的基类来
构造过程:
1、先造虚基类A
由 D的构造函数直接调用 A的构造函数(B和C的造函数不再调用 A)
2、按照声明顺序构造:先 B,后 C
3、D的自身构造

         解决菱形继承的问题。

this指针调整

在多继承中,当派生类指针转换为基类指针时,可能需要调整this指针的值:

Derived* d = new Derived;
Base2* b2 = d;  // 可能需要调整指针值

对象构造与析构过程

  1. 分配内存

  2. 构造基类子对象

  3. 构造成员对象

  4. 执行构造函数体

  5. 析构顺序相反

运行时类型识别(RTTI)

通过type_info对象实现,通常与虚函数表存储在一起。

性能考虑

  1. 虚函数调用比普通函数调用多一次间接寻址

  2. 多重继承可能增加空间开销

  3. 虚继承会增加访问虚基类成员的开销

理解C++对象模型有助于编写更高效的代码,并更好地理解C++的底层机制。

http://www.xdnf.cn/news/1191943.html

相关文章:

  • linux练习题
  • linux内核电源管理
  • JavaWeb(苍穹外卖)--学习笔记11(Filter(过滤器) 和 Interceptor(拦截器))
  • JavaScript中.splice()的用法
  • 从零开始大模型之编码注意力机制
  • HTML5 Canvas 绘制圆弧效果
  • 适用于5V/12V低输入的负载点电源应用20V/6A单片式双通道同步降压调整器
  • 面试150 IPO
  • C#其他知识点
  • 实验-OSPF多区域
  • ubuntu下docker安装thingsboard物联网平台详细记录(附每张图)
  • KTO:基于行为经济学的大模型对齐新范式——原理、应用与性能突破
  • 栈----3.字符串解码
  • C语言函数精讲:从入门到精通( 指针(5))
  • 秋招Day20 - 微服务 - 概念
  • kafka的消费者负载均衡机制
  • 嵌入式硬件篇---有线串口通信问题
  • OpenCV图像梯度、边缘检测、轮廓绘制、凸包检测大合集
  • IntelliJ IDEA 中左上方未显示项目根目录问题
  • 数据库索引详解:原理、设计原则与应用场景
  • 渲染篇(二):解密Diff算法:如何用“最少的操作”更新UI
  • Word文档转HTML查看器(字体颜色、字体背景、超链接、图片、目录等全部转换为html),统计Word文档段落数量、图片数量、表格数量、列表数量
  • HTML5元素相关补充
  • 小架构step系列26:Spring提供的validator
  • CS231n-2017 Lecture7训练神经网络(二)笔记
  • 三防平板搭载2D扫描头:工业数据采集的革新利器
  • Vue3 学习教程,从入门到精通,Vue3 样式绑定语法详解与案例(17)
  • 零基础 “入坑” Java--- 十四、【练习】图书小系统
  • 一、Spring框架结构组成详解
  • Transformer:颠覆NLP的自注意力革命