C++对象模型

news2024/11/26 16:48:59

思考:对于实现平面一个点的参数化。C++的class封装看起来比C的struct更加的复杂,是否意味着产生更多的开销呢?

实际上并没有,类的封装不会产生额外的开销,其实,C++中在布局以及存取上的额外开销是virtual引起的。

C++对象模式

在C++中,有两种class data members:静态成员和非静态成员。有三种class member functions:静态的,非静态的以及虚函数

C++对象模型

Nonstatic datamembers 被配置于每一个class object之内。static data members则被存放在个别的class object之外。

static 和nonstatic function members也被存放在class object之外(仅一份)

virtual fuction:每一个class产生一堆指向virtual table(vtbl)中;每一个class object被安插一个指针,vptr指向相关的virtual table

(图示) file

关于继承

继承关系也可指定为虚拟(也就是共享)

(图示) file

在虚拟继承的情况下,base class不管在继承串链中被派生多少回,永远只存在一个实例(subobject)

(图示) file

对象模型如何影响程序

(图示) file

对象的差异

程序模型(类C)

char boy[] = "Danny";
char *p_son;
...
p_son = new char [strlen(boy) + 1];
strcpy(p_son,boy);
...
if(!strcmp(p_son,boy))
    take_to_disneyland(boy)

抽象数据类型(ADT)

string girl = "Anna";
string daughter;
...
//string :: operator = ()
daughter = girl;
//string::operator==()
if(girl == daughter)
   take_to_disneyland(girl);

面对对象编程

void
check_in(Library_materials *pmat)
{
if(pmat->late() )
    pmat->fine();
pmat->check_in();
if(Lender *plend = pmat->reserved())
   pmat->notify(plend);
}

多态实现

在C++中,多态只存在于一个个的public class体系中

有这样三种多态支持:

经由一组隐式的转化操作。例如把一个derived class指针转化为一个指向public base type的指针;

shape *ps = new circle();

经由virtual fuction机制

ps->rotate();

经由dynamic_cast和typeid运算符;

if(circle pc = dynamic_cast<circle>(ps))..

思考:需要多大内存才能够表现一个class object?

非静态数据成员(non-static data members):非静态数据成员是每个类对象都需要独立分配的,所以其大小需计算在内。

虚函数表指针(vptr):如果类含有虚函数,则需要一个指针指向虚函数表,用于动态绑定。这个指针的大小通常是机器字长,比如64位系统为8字节。

内存对齐填充(padding):为了优化内存访问效率,编译器会在类成员之间插入内存对齐填充。

其他系统占用空间:除了类自身需要的空间外,一些编译器和系统会在类对象中预留一些额外空间,例如运行时类型信息(RTTI)。

所以一个类对象所需内存的计算公式概略为:对象内存 = 非静态数据成员大小总和 + (含虚函数则加上vptr指针大小) + 填充大小 + 其他系统占用大小

其中除了非静态数据成员外,其他部分大小在不同系统和编译器下可能有所不同。

一个更准确的计算对象大小的方法是:在程序中使用sizeof运算符,它会返回这个平台下该类对象的确切字节大小。 

注意:

类中静态数据成员(static data member)与对象的内存大小无关。

静态数据成员不属于类的任何一个对象,只会在程序的整个生命周期内有一份内存拷贝存在。

所以静态数据成员不会影响每个类对象实例的内存需求。 指针的类型

例子:

ZooAnimal  *px;
int *pi;
Array<string>*pta;

从内存上面看,这几个指针没有什么区别,大小是一个机器地址。(word)

但是其实,“指针类型”会教导编译器如何解释某个特定地址中的内存内容以及大小。

(图示) file 进一步探讨:

Bear b; ZooAnimal za=b; //译注:这会引起切割(sliced) //调用 ZOOAnimal::rotate() za.rotate();

为什么rotate所调用的是ZooAnimal实例而不是Bear实例?此外,如果初始化函数(译注:应用于上述assignment操作发生时)将一个object内容完整拷贝到另个object去,为什么za的vptr 不指向Bear的virtual table?

ZooAnimal za = b;这行代码中,使用基类ZooAnimal的引用或指针初始化时,编译器会:

  1. 为za分配一个ZooAnimal类型的空间
  2. 把b对象中的ZooAnimal部分的数据拷贝过来

也就是说,这个赋值操作生成了一个新的ZooAnimal对象,它只包含了原b对象中的ZooAnimal部分的数据和函数,丢失了b作为Bear的额外信息。

然后za调用rotate()时,编译器根据静态类型(ZooAnimal)调用ZooAnimal::rotate(),而不是动态类型Bear::rotate()。

如果想保留全部信息,可以使用指针或引用:cpp Bear b; ZooAnimal* za = &b; za->rotate(); // 调用Bear::rotate()

或者使用动态绑定:cpp Bear b; ZooAnimal& za = b; za.rotate(); // 调用Bear::rotate()

编译器在将一个class object指定给另一个class object之间做出仲裁,编译器必须保证如果某个object含义一个或者以上的vptrs,那些vptrs不会被base class 改变。

补充:

当一个base class object 被直接初始化为(或是被指定为)一个 derived classobject 时,derivedobject 就会被切(sliced)以塞入较小的 base type 内存中,derivedtype将没有留下任何蛛丝马迹。多态于是不再呈现,而一个严格的编译器可以在编译时期解析一个“通过此object而触发的virtualfunction调用操作”,因而回避virtual机制。如果virtualfunction 被定义为inline,则更有效率上的大收获。

本文由博客一文多发平台 OpenWrite 发布!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1173249.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

unittest 通过loadTestsFromName执行多个测试case

这段代码是一个使用unittest模块编写的测试运行程序。它的主要功能是加载其他Python文件中的测试用例并运行这些测试用例。 首先&#xff0c;定义了一个主测试类MainTestCase&#xff0c;该类继承自unittest.TestCase。在这个类中&#xff0c;可以添加各种测试方法来测试不同的…

产品经理入门学习(四):项目立项

参考引用 黑马-产品经理入门基础课程 1. 项目方案 1.1 主要阶段 立项阶段 基本方案&#xff1a;要做个什么项目&#xff0c;为什么要做这个项目&#xff0c;这个项目的作用和价值分别有哪些 上线阶段 设计阶段 运营阶段 开发阶段 总结阶段 测试阶段 2. 可行性分析 可…

Python语言_single_color_共140种--全平台可用

Python语言_single_color_共140种–全平台可用

3、Dockerfile 深入与其他细节

Dockerfile 在 Docker 中创建镜像最常用的方式&#xff0c;就是使用 Dockerfile。Dockerfile 是一个 Docker 镜像 的描述文件&#xff0c;我们可以理解成火箭发射的 A、B、C、D…的步骤。Dockerfile 其内部包含了一 条条的指令&#xff0c;每一条指令构建一层&#xff0c;因此每…

045_第三代软件开发-U盘监测

第三代软件开发-U盘监测 文章目录 第三代软件开发-U盘监测项目介绍U盘监测原理解释源代码 关键字&#xff1a; Qt、 Qml、 USB、 Disk、 文件 项目介绍 欢迎来到我们的 QML & C 项目&#xff01;这个项目结合了 QML&#xff08;Qt Meta-Object Language&#xff09;和…

1.如何实现统一的API前缀-web组件篇

文章目录 1. 问题的由来2.实现原理3. 总结 1. 问题的由来 系统提供了 2 种类型的用户&#xff0c;分别满足对应的管理后台、用户 App 场景。 两种场景的前缀不同&#xff0c;分别为/admin-api/和/app-api/&#xff0c;都写在一个controller里面&#xff0c;显然比较混乱。分开…

storm安装手册及笔记

图解Storm相关概念 图解storm的并发机制 安装Storm的步骤 1、安装一个zookeeper集群 2、上传storm的安装包&#xff0c;解压 3、修改配置文件storm.yaml #所使用的zookeeper集群主机 storm.zookeeper.servers: - "weekend05" - "weekend06"…

亚马逊 JDK下载地址

下载地址 https://docs.aws.amazon.com/corretto/选择版本 选择操作系统 比如 windows64 位 可以选择安装包或者解压版本 msi 的为安装版 zip 的为解压版

微积分第一章函数与极限

1.正反三角函数的导数 2.常用等价无穷小 3.正反三角函数转化&#xff1a; 1.secx1/cosx 2.cecx1/sinx 3.cotx1/tanx 4.基本数学思想&#xff1a; 1.有限式子与无限式子&#xff1a;在面对无限个式子运算时&#xff0c;大体思路为两个方面&#xff0c;第一个为放缩&#xff…

静态、友好、内在:解析C++中的这些特殊元素和对象复制的优化

W...Y的主页 &#x1f60a; 代码仓库分享&#x1f495; &#x1f354;前言&#xff1a; 前面我们学习了C中关于类与对象的许多知识点&#xff0c;今天我们继续学习类与对象&#xff0c;最后再总结一下类与对象中的一些关键字内容&#xff0c;以及需要注意的细节。满满的干货…

【H.264】RTP h264 码流 实例解析分析 3 : webrtc

【srs】SRS检测IBMF还是annexb 【H.264】RTP h264 码流 实例解析分析 2 : mediasoup收包 mediasoup 并没完整解析rtp包的内容,可能与mediasoup 只需要转发,不需要解码有关系。 webrtc 本身都是全的。 m98代码,先说关键: webrtc的VideoRtpDepacketizer 第一:对RTPVideoType…

年终述职技巧

一个共识 给个交代 复盘 给自己的交代 展示 给公司的交代 三维构思法 认知与成长 以己为师 萃取与迭代 以事为师 响应与前瞻 以人为师&#xff08;“作者视角”转变为“观众视角”&#xff0c;听懂、感兴趣、认可、有收获&#xff09; 六点通关术 论证价值点 工作成果&#x…

从《lc114. 二叉树展开为链表》到《lc-LCR 155二叉搜索树转化为排序的双向链表》

1 lc114. 二叉树展开为链表 1.1 描述 进阶&#xff1a;你可以使用原地算法&#xff08;O(1) 额外空间&#xff09;展开这棵树吗&#xff1f; 1.2 解法一&#xff1a; 先序遍历这棵树并且将节点加入到一个list中&#xff0c;随后按顺序将list中的每一个元素的left指针置换为…

AGV 导航方法总体设计与分析

导航方案设计 导航方法分为三个部分——路径规划、实时定位、轨迹纠正。 视觉定位模块 主要有三个工作任务&#xff1a;利用二维码定位对 AGV 初始位姿 进行矫正&#xff0c;保证 AGV 初始运动时其运动轨迹能够与道路平行&#xff1b;利用 ORBSLAM 定位能够实时的获得 AGV 在…

LeetCode热题100——链表

链表 1. 相交链表2. 反转链表3. 回文链表4. 环形链表5. 合并两个有序链表 1. 相交链表 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点&#xff0c;返回 null 。 // 题解&#xff1a;使用A/B循环遍…

Windows Server 2019安装docker服务

离线状态下&#xff0c;使用脚本在Windows Server 2019环境中安装docker服务。 1.安装脚本 在微软官方网站中&#xff0c;找到脚本并下载&#xff1a; 准备 Windows 操作系统容器 | Microsoft Learn 脚本地址&#xff1a; https://raw.githubusercontent.com/microsoft/Win…

数字化饲料工厂中常见的系统及其介绍

数字化饲料工厂是基于先进技术和数字化平台构建的现代化饲料生产系统&#xff0c;它包含了多种软件、硬件和基础设施系统。以下是数字化饲料工厂中常见的系统及其介绍&#xff1a; 一、自动化控制系统&#xff1a;包括PLC&#xff08;可编程逻辑控制器&#xff09;系统、SCADA&…

R语言 PPT 预习+复习

什么狗吧发明的结业考&#xff0c;站出来和我对线 第一章 绪论 吊码没有&#xff0c;就算考R语言特点我也不背&#xff0c;问就是叫么这没用。 第二章 R语言入门 x<-1:20 赋值语句 x 1到20在x上添加均值为0、标准差为2的正态分布噪声 y <- x rnorm (20, 0, 2) 这…

SOEM源码解析——eeprom_read(读EEPROM)

0 工具准备 1.SOEM-master-1.4.0源码1 eeprom_read函数总览 eeprom_read函数在SOEM源码的路径如下&#xff1a;test->linux->eepromtool->eepromtool.c&#xff0c;功能是读取指定字地址和长度的EEPROM数据&#xff1a; /*** brief 读取EEPROM数据* * param slave …

Vue3:一页多题答案校正及radio和checkbox混合使用

一页多题&#xff0c;类型包括单选&#xff0c;判断多选&#xff0c;涉及radio和checkbox同时使用&#xff0c;答案校正数据匹配&#xff0c;正确答案格式化&#xff0c;答案提交数据格式化&#xff0c;数据提交。 效果&#xff1a; 数据获取&#xff1a; 数据提交&#xff1a…