C++对象模型(8)-- 数据语义学:this指针

1、this指针的认识

this 是 C++ 中的一个关键字,也是一个 const 指针 ,它指向当前对象,通过它可以访问当前对象的所有成员。所谓当前对象,是指正在使用的对象。

假如有这么一个类:

class Base {
public:int b_i;int b_j;void print() {printf(" this的地址:%p\n", this);}
};

那么这个Base类对象的this指针指向的就是变量b_i的地址。

2、没有虚函数的情况

this指针调整一般存在于多重继承的情况下。

我们先进行代码演示:

class X {
public:int x_i;X() {cout << " X::X()的this指针是:" << this << endl;}void funcX() {cout << " X::funcX()的this指针是:" << this << endl;}
};class Y {
public:int y_i;Y() {cout << " Y::Y()的this指针是:" << this << endl;}void funcY() {cout << " Y::funcY()的this指针是:" << this << endl;}
};class Z : public X, public Y {
public:int z_i;Z() {cout << " Z::Z()的this指针是:" << this << endl;}void funcZ() {cout << " Z::funcZ()的this指针是:" << this << endl;}
};int main()
{Z z;z.funcX();z.funcY();z.funcZ();
}

类Z对象的内存布局是这样的:

代码的输出结果是这样的:

从输出结果可以画出this指针的指向是下面这样的。

这里有2个要点:

(1) 这里Z类先继承X、再继承Y。派生类Z的地址和第1个继承的基类X的地址是相同的。

(2) 调用哪个子类的成员函数,这个this指针就会被编译器自动调整到对象内存布局中对应类对象的起始地址。

3、父类没有虚函数、子类有虚函数

class X {
public:int x_i;X() {cout << " X::X()的this指针是:" << this << endl;}void funcX() {cout << " X::funcX()的this指针是:" << this << endl;}
};class Y : public X {
public:int y_i;Y() {cout << " Y::Y()的this指针是:" << this << endl;}void funcY() {cout << " Y::funcY()的this指针是:" << this << endl;}virtual void virFuncY() { }
};int main()
{Y y;printf(" 变量a的偏移量:%d\n", &X::x_i);printf(" 变量c的偏移量:%d\n", &Y::y_i);y.funcX();y.funcY();
}

这时输出的结果是这样的:

从输出结果可以看到:

(1) 父类X的this指针比子类X高4个字节,类X的变量x_i的偏移量是0。

这个可以这么理解:虚函数表指针vptr总是在对象的头部,因为父类X没有虚函数表指针,所以父类X对象的指针要往下跳过vptr(4个字节),然后就直接访问变量x_i,所以x_i的偏移量是0。

(2) 类Y的变量y_i的偏移量是8。因为vptr、int x_i各占4个字节,所以变量y_i的偏移量是 4 + 4 = 8。

4、父类、子类都有虚函数

我们给类X加上虚函数:

virtual void virFuncX() { }

然后看输出结果:

从结果我们可以看到,父类X的this指针和类Y的this指针相同了,且变量x_i的偏移量变成了4。这4个字节是虚函数表指针所占用的空间。

5、多重继承且父类都带虚函数

我们在原来的代码上再添加1个新类Z,且让Z继承自类X、Y:

class Z : public X, public Y {
public:int z_i;Z() {cout << " Z::Z()的this指针是:" << this << endl;}void funcZ() {cout << " Z::funcZ()的this指针是:" << this << endl;}
};int main()
{Z z;printf(" 变量x_i的偏移量:%d\n", &X::x_i);printf(" 变量y_i的偏移量:%d\n", &Y::y_i);printf(" 变量z_i的偏移量:%d\n", &Z::z_i);z.funcX();z.funcY();z.funcZ();
}

输出结果:

因为2个父类都有虚函数,所以类Z会继承这2个虚函数表指针。但2个父类X、Y是并级的,对于每一个父类对象来说,它的成员变量都会偏移4个字节。而子类的变量会偏移16个字节。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[NewStarCTF 2023 公开赛道] week1 Crypto

brainfuck 题目描述&#xff1a; [>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<-]>>>>>>>.>----.<-----.>-----.>-----.<<<-.>>..…

论文解析——异构多芯粒神经网络加速器

作者 朱郭益, 马胜&#xff0c;张春元, 王波&#xff08;国防科技大学计算机学院&#xff09; 摘要 随着神经网络技术的快速发展, 出于安全性等方面考虑, 大量边缘计算设备被应用于智能计算领域。首先&#xff0c;设计了可应用于边缘计算的异构多芯粒神经网络加速器其基本结构…

TCP相关面试题

TCP相关面试题 题目1 介绍一下TCP三次握手的过程 介绍TCP三次握手应该从3个方面进行回答&#xff0c;分别是数据包名称&#xff0c;客户端与服务端的状态变化&#xff0c;数据包的序号变化。而不能只是简单回答发送的数据包名称。 TCP三次握手的过程如下&#xff1a; 从数据…

关于Jupyter notebook 创建python3 时进去不能重命名问题及不能编程问题

首先写这篇博客时&#xff0c;已经被这个问题折磨了三天&#xff0c;看了很多博客&#xff0c;其实解决这个问题的关键就是要么没有下pyzmq或者等级太高&#xff0c;要么等级太低&#xff0c;首先我会按照我思路来。 问题如图&#xff1a; 1.自动换行 2.不能重命名 我的解决办…

安装torchtext遇到的坑及解决办法

刚开始秉着需要什么就pip install什么的原则直接pip install torchtext&#xff0c;结果&#xff1a; 把我这个环境打乱了&#xff0c;自作主张的删掉之前的很多包重新安装了其他版本的包而不是自适应的安装当前torch所对应的torchtext。因为这个环境比较重要也用在其他的工程…

MySQL详解 七:数据库高级语句(视图表、存储过程)

文章目录 1. create view ---- (视图表)1.1 视图的简单介绍1.2 基本语法1.2.1 创建视图表1.2.2 查看视图表1.2.3 删除视图表1.2.4 修改视图表 1.3 通过视图表得出无交集 2. case语句3. 空值&#xff08;null&#xff09; 和 无值&#xff08; &#xff09; 的区别4. 正则表达式…

CSS盒子定位的扩张

定位的扩展 绝对定位&#xff08;固定定位&#xff09;会完全压住盒子 浮动元素不会压住下面标准流的文字&#xff0c;而绝对定位或固定位会压住下面标准流的所有内容 如果一个盒子既有向左又有向右&#xff0c;则执行左&#xff0c;同理执行上 显示隐藏 display: none&…

【C语言】字符函数和内存操作函数

大家好&#xff0c;我是苏貝&#xff0c;本篇博客带大家了解字符函数和内存操作函数&#xff0c;如果你觉得我写的还不错的话&#xff0c;可以给我一个赞&#x1f44d;吗&#xff0c;感谢❤️ 目录 一.字符函数1.1 字符分类函数1.2 字符转换函数 二.内存操作函数2.1 memcpy2.2…

Java @Override 注解

在代码中&#xff0c;你可能会看到大量的 Override 注解。 这个注解简单来说就是让编译器去读的&#xff0c;能够避免你在写代码的时候犯一些低级的拼写错误。 Java Override 注解用来指定方法重写&#xff08;Override&#xff09;&#xff0c;只能修饰方法并且只能用于方法…

ctfshow-web11(session绕过)

php代码审计&#xff1a; function replaceSpecialChar($strParam){$regex "/(select|from|where|join|sleep|and|\s|union|,)/i";return preg_replace($regex,"",$strParam);} 首先定义了一个函数&#xff0c;主要是使用preg_replace函数对我们提交的内…

一文告知HTTP GET是否可以有请求体

HTTP GET是否可以有请求体 先说结论&#xff1a; HTTP协议没有规定GET请求不能携带请求体&#xff0c;但是部分浏览器会不支持&#xff0c;因此不建议GET请求携带请求体。 HTTP 协议没有为 GET 请求的 body 赋予语义&#xff0c;也就是即不要求也不禁止 GET 请求带 body。大多数…

1797_GNU pdf阅读器evince

全部学习汇总&#xff1a; GreyZhang/g_GNU: After some years I found that I do need some free air, so dive into GNU again! (github.com) 近段时间经历了很多事情&#xff0c;终于想找一点技术上的自由气氛。或许&#xff0c;没有什么比GNU的一些软件探索更适合填充这样的…

关于flink重新提交任务,重复消费kafka的坑

异常现象1 按照以下方式设置backend目录和checkpoint目录&#xff0c;fsbackend目录有数据&#xff0c;checkpoint目录没数据 env.getCheckpointConfig().setCheckpointStorage(PropUtils.getValueStr(Constant.ENV_FLINK_CHECKPOINT_PATH)); env.setStateBackend(new FsStat…

[CISCN2019 华北赛区 Day1 Web5]CyberPunk 二次报错注入

buu上 做点 首先就是打开环境 开始信息收集 发现源代码中存在?file 提示我们多半是包含 我原本去试了试 ../../etc/passwd 失败了 直接伪协议上吧 php://filter/readconvert.base64-encode/resourceindex.phpconfirm.phpsearch.phpchange.phpdelete.php 我们通过伪协议全…

C++ 类和对象篇(八) const成员函数和取地址运算符重载

目录 一、const成员函数 1. const成员函数是什么&#xff1f; 2. 为什么有const成员函数&#xff1f; 3. 什么时候需要使用const修饰成员函数&#xff1f; 二、取地址运算符重载 1. 为什么需要重载取地址运算符&#xff1f; 2. 默认取地址运算符重载函数 3. 默认const取地址运…

查看当前目录下文件所占用内存 du -sh

1. du -sh 查看当前目录下文件所占用内存 2.查看当前文件夹下&#xff0c;每个文件所占用内存 du -ah --max-depth1/

Linux命令笔记

终端命令格式&#xff1a; bash command [-options] [parameter] 7个常见Linux命令&#xff1a; 01 ls | list | 查看当前文件夹下的内容 02 pwd | print work directory | 查看当前所在文件夹 03 cd [目录名] | change directory | 切换文件夹 04 touch [文件名] | touc…

基于WTMM算法的图像多重分形谱计算matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1、WTMM算法概述 4.2、WTMM算法原理 4.2.1 二维小波变换 4.2.2 模极大值检测 4.2.3 多重分形谱计算 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部…

云原生监控系统Prometheus:基于Prometheus构建智能化监控告警系统

目录 一、理论 1.Promethues简介 2.监控告警系统设计思路 3.Prometheus监控体系 4.Prometheus时间序列数据 5.Prometheus的生态组件 6.Prometheus工作原理 7.Prometheus监控内容 8.部署Prometheus 9.部署Exporters 10.部署Grafana进行展示 二、实验 1.部署Prometh…

项目设计:YOLOv5目标检测+机构光相机(intel d455和d435i)测距

1.介绍 1.1 Intel D455 Intel D455 是一款基于结构光&#xff08;Structured Light&#xff09;技术的深度相机。 与ToF相机不同&#xff0c;结构光相机使用另一种方法来获取物体的深度信息。它通过投射可视光谱中的红外结构光图案&#xff0c;然后从被拍摄物体表面反射回来…