Day 15 C++对象模型和this指针
目录
C++对象模型
类内的成员变量和成员函数分开存储
总结
this指针
概念
示例
用途
当形参和成员变量同名时
在非静态成员函数中,如果希望返回对象本身
例子
空指针访问成员函数
示例
const修饰成员函数
常函数(const member function)
常对象(const object)
关键字mutable
C++对象模型
是指描述C++中对象在内存中的布局和组织方式的规范。它涉及到类的成员变量、成员函数以及继承关系等方面。
在C++对象模型中,一个类的对象通常由两部分组成:成员变量和成员函数。
C++对象模型描述了在C++中对象的内存布局和组织方式。以下是一些关键概念:
成员变量的布局:成员变量按照声明的顺序在内存中排列。对于非静态成员变量,每个对象都有其自己的独立拷贝。对于静态成员变量,所有对象共享同一份拷贝。
成员函数的存储:成员函数通常不直接存储在对象中,而是存储在类的代码段中。每个成员函数只有一份实现,在内存中共享。当调用成员函数时,通过this指针来访问当前对象的成员。
this指针:this指针是一个隐含的指向当前对象的指针。它允许在成员函数内部通过this->来访问当前对象的成员变量和成员函数。
继承关系的布局:当一个类继承自另一个类时,子类对象的内存布局包含了基类部分和派生类自身的部分。基类的成员变量按照声明顺序排列在子类对象的前部分。
虚函数表(Vtable):如果类中存在虚函数,编译器会生成一个虚函数表。虚函数表是一个指针数组,存储了虚函数的地址。每个对象中存在一个指向其对应类虚函数表的指针(虚函数指针)。
多重继承:当一个类从多个基类派生时,对象内存布局会根据继承顺序依次包含各个基类的部分。
需要注意的是,C++对象模型的具体实现因编译器而异。不同的编译器可能存在一些细微差异,但大体上遵循了C++标准对于对象模型的规定。了解对象模型对于理解C++的底层运作机制和进行性能优化非常有帮助。
类内的成员变量和成员函数分开存储
成员变量在内存中按照定义的顺序排列,每个成员变量在内存中占据一定的空间。其中,基本数据类型的成员变量直接存储其值,而对象类型的成员变量存储的是对象的地址。
成员函数则不直接存储在对象内存中,而是存储在类的代码段中。每个成员函数只有一份,被所有对象共享。当调用成员函数时,通过this指针来访问当前对象的成员变量和调用其他成员函数。
总结
非静态成员变量占对象空间
静态成员变量不占对象空间
只有非静态成员变量才属于类的对象上
函数(包括静态成员函数)也不占对象空间,所有函数共享一个函数实例
this指针
概念
this指针是C++中的一个隐含指针,它指向当前对象。它可以在类的非静态成员函数中使用,用于访问当前对象的成员变量和成员函数。
具体来说,当我们在类的成员函数内部使用成员变量或调用其他成员函数时,编译器会将这些代码转换为使用this指针来访问。this指针是一个指向当前对象的常量指针,它的类型是当前类的指针类型。
每一个非静态成员函数只会诞生一份函数实例,也就是说多个同类型的对象会共用一块代码
通过this指针可以区分那个对象调用这一块代码。
this指针是隐含于每一个非静态成员函数内的一种指针
this指针不需要定义,直接使用即可
对象指针访问属性要用 -> , 例如this->x = value(等价于(*this).x = value)
示例
class MyClass {
public:int x;void setX(int value) {this->x = value; // 使用this指针访问成员变量}void printX() {std::cout << "x = " << this->x << std::endl; // 使用this指针访问成员变量}void callAnotherFunction() {this->printX(); // 使用this指针调用其他成员函数}
};
在上面的示例中,setX()函数和printX()函数中使用了this指针来访问成员变量x。在setX()函数中,this->x = value(等价于(*this).x = value)将传入的value赋值给当前对象的成员变量x。在printX()函数中,使用this->x将当前对象的成员变量x输出到标准输出。
另外,callAnotherFunction()函数中使用this指针调用printX()函数。this->printX()等价于(*this).printX(),它调用了当前对象的printX()成员函数。
用途
当形参和成员变量同名时
在非静态成员函数中,可以使用this指针来区分它们。this->age = age表示将传入的参数值赋给当前对象的成员变量age。通过使用this指针,我们明确指出要操作的是成员变量而不是形参。
在非静态成员函数中,如果希望返回对象本身
可以使用return *this语句。这样可以实现链式调用,即在一个对象上连续调用多个成员函数。
例子
class MyClass {
public:int x;MyClass& setX(int value) { // 返回对象本身的引用this->x = value;return *this;}void printX() {std::cout << "x = " << this->x << std::endl;}
};int main() {MyClass obj;obj.setX(5).printX(); // 链式调用return 0;
}
空指针访问成员函数
在C++中,空指针也可以调用成员函数,但是需要注意使用到this指针时的判断,以确保代码的健壮性和安全性。
当空指针调用成员函数时,由于没有有效的对象实例,this指针将为nullptr。如果在成员函数中没有使用this指针访问成员变量或调用其他成员函数,则可以安全地使用空指针调用。
当成员函数中使用了this指针时,就需要进行合适的判断来避免空指针解引用错误。
示例
#include <iostream>class MyClass {
public:void memberFunction() {std::cout << "Inside memberFunction" << std::endl;}
};int main() {MyClass* ptr = nullptr;// 空指针调用成员函数ptr->memberFunction();return 0;
}
在上述代码中,我们声明了一个名为MyClass的类,其中有一个成员函数memberFunction()。在主函数中,将一个空指针ptr初始化为nullptr。然后,我们尝试使用空指针ptr来调用成员函数memberFunction()。尽管ptr是空指针,但由于memberFunction()函数内部没有使用this指针访问成员变量或调用其他成员函数,因此可以安全地运行该程序。输出结果为"Inside memberFunction"。
请注意,在实际应用中,应该始终确保指针是有效的,以避免潜在的错误和崩溃。
const修饰成员函数
常函数(const member function)
常函数是指在成员函数的声明和定义的末尾加上const关键字。常函数承诺不会修改类的任何非静态成员变量。这意味着在常函数内部,不能对非静态成员变量进行赋值操作或调用可能修改成员状态的非const函数。
class MyClass {
public:void someFunction() const {// 在常函数中只能访问类的成员变量,不能修改它们}
};
成员函数后加const后我们称为这个函数为常函数
常函数内不可以修改成员属性
成员属性声明时加关键字mutable后,在常函数中依然可以修改
常对象(const object)
常对象是指在对象声明之前加上const关键字,从而将其声明为常对象。常对象的特点是其成员变量的值在创建后不能被修改,并且只能调用常函数。
const MyClass obj;
声明对象前加const称该对象为常对象
常对象只能调用常函数
关键字mutable
即使在常函数中,普通的成员变量依然无法修改,包括在常对象中。但是,如果某个成员变量声明时使用了关键字mutable
,则可以在常函数中修改该成员变量的值。mutable
关键字的作用是允许常函数改变被修饰的成员变量。
综上所述,常函数和常对象的使用可以提高代码的安全性和可读性。
常函数用于声明不会修改类状态的函数
而常对象用于保护成员变量的不可修改性,并限制只能调用常函数。
class Person {
public:Person() {m_A = 0;m_B = 0;}//this指针的本质是一个指针常量,指针的指向不可修改//如果想让指针指向的值也不可以修改,需要声明常函数void ShowPerson() const {//const Type* const pointer;//this = NULL; //不能修改指针的指向 Person* const this;//this->mA = 100; //但是this指针指向的对象的数据是可以修改的//const修饰成员函数,表示指针指向的内存空间的数据不能修改,除了mutable修饰的变量this->m_B = 100;}void MyFunc() const {//mA = 10000;}public:int m_A;mutable int m_B; //可修改 可变的
};//const修饰对象 常对象
void test01() {const Person person; //常量对象 cout << person.m_A << endl;//person.mA = 100; //常对象不能修改成员变量的值,但是可以访问person.m_B = 100; //但是常对象可以修改mutable修饰成员变量//常对象访问成员函数person.MyFunc(); //常对象只能调用const的函数}int main() {test01();system("pause");return 0;
}
相关文章:
Day 15 C++对象模型和this指针
目录 C对象模型 类内的成员变量和成员函数分开存储 总结 this指针 概念 示例 用途 当形参和成员变量同名时 在非静态成员函数中,如果希望返回对象本身 例子 空指针访问成员函数 示例 const修饰成员函数 常函数(const member function&…...
HarmonyOS/OpenHarmony元服务开发-卡片生命周期管理
创建ArkTS卡片,需实现FormExtensionAbility生命周期接口。 1.在EntryFormAbility.ts中,导入相关模块。 import formInfo from ohos.app.form.formInfo; import formBindingData from ohos.app.form.formBindingData; import FormExtensionAbility from …...
软件工程01
软件工程原则: 开闭原则: open closed principle : 对扩展开放,对修改关闭,,,只让扩展,不让修改,用新增的类去替代修改的类 扩展之后,代码不用改变ÿ…...

UML/SysML建模工具更新(2023.7)(1-5)有国产工具
DDD领域驱动设计批评文集 欢迎加入“软件方法建模师”群 《软件方法》各章合集 最近一段时间更新的工具有: 工具最新版本:Visual Paradigm 17.1 更新时间:2023年7月11日 工具简介 很用心的建模工具。支持编写用例规约。支持文本分析和C…...
Mac plist文件
macOS、iOS、iPadOS的应用程序都可能会有plist配置文件,他是苹果系列操作系统特有的配置文件。 plist的本质是个xml格式的文本文件,英文全称是property list,文件后缀使用.plist。 对于普通用户来说,基本不用管plist文件是什么&…...

基于Java+SpringBoot+vue前后端分离校园周边美食探索分享平台设计实现
博主介绍:✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专…...
【openwrt】package介绍
openwrt package介绍 OpenWrt 构建系统主要围绕package的概念展开。不管是什么软件,几乎都对应一个package。 这几乎适用于系统中的所有内容:HOST工具、交叉编译工具链、Linux 内核、内核mod、根文件系统和上层的应用软件。 一个 OpenWrt package本质上…...

vue 封装一个鼠标拖动选择时间段功能
<template><div class"timeRange"><div class"calendar"><table><thead><tr><th rowspan"6" class"weekRow"><b>周/时间</b></th><th colspan"24"><…...
ubuntu22.0安装Barrier局域网共享鼠标键盘
ubuntu22.0安装Barrier局域网共享鼠标键盘 参考网站安装步骤客户端一直开启中解决 参考网站 https://idroot.us/install-barrier-ubuntu-22-04/ 安装步骤 sudo apt update sudo apt upgrade sudo apt install wget apt-transport-https gnupg2 software-properties-common s…...
ffmpeg常用功能博客导航
FFmpeg 是一个处理视频和音频内容的开源工具库,可以实现编码、解码、转码、流媒体和后处理等服务。 推荐博客: 常见命令和使用案例 用ffmpeg转mov为mp4格式 FFmpeg 常用命令 FFmpeg 常用命令编辑音/视频(转换格式、压缩、裁剪、截图、切分合…...

shopee,lazada,etsy店群如何高效安全的管理
对于电商卖家来说,要经营多个店铺,管理多个账号是非常常见的操作。为了避免账号关联被平台识别出来,需要使用防关联的浏览器来进行操作 1、支持多平台 支持同时管理多个电商平台店铺,Shopee、Lazada、etsy、poshmark、vinted等&…...

【计算复杂性理论】证明复杂性(八):命题鸽巢原理(Propositional Pigeonhole Principle)的指数级归结下界
往期文章: 【计算复杂性理论】证明复杂性(Proof Complexity)(一):简介 【计算复杂性理论】证明复杂性(二):归结(Resolution)与扩展归结ÿ…...

使用DataX实现mysql与hive数据互相导入导出
一、概论 1.1 什么是DataX DataX 是阿里巴巴开源的一个异构数据源离线同步工具,致力于实现包括关系型数据库(MySQL、Oracle 等)、HDFS、Hive、ODPS、HBase、FTP 等各种异构数据源之间稳定高效的数据同步功能。 1.2 DataX 的设计 为了解决异构数据源同步问题…...

语音转录成文本:AI Transcription for mac
AI Transcription是一种人工智能技术,它可以将音频和视频文件转换成文本格式。这种技术可以帮助用户快速地将大量的音频和视频内容转换成文本格式,方便用户进行文本分析、搜索和编辑等操作。 以下是AI Transcription的几个特点: 高效性。AI …...

[nlp] TF-IDF算法介绍
(1)TF是词频(Term Frequency) 词频是文档中词出现的概率。 (2) IDF是逆向文件频率(Inverse Document Frequency) 包含词条的文档越少,IDF越大。...
一些感想,写在8月之前
最近换工作了,离开了一个奋斗了4年多的公司,现在在新公司,还在培训中,不那么忙了,就写写最近的想法吧。 因为最近一直在研究框架和搭项目框架,所以就想把一些工作上的过程记录下来,以备不时之需…...

推动数字经济高质量发展需破解三大挑战
随着信息技术的飞速发展,数字经济已成为全球经济发展的重要驱动力。数字经济以其高效、便捷、创新的特点,深刻改变着传统产业和商业模式,为经济发展带来新的活力和动力。然而,要实现数字经济的高质量发展,仍然面临着三…...

Pycharm工具Python开发自动添加注释(详细)
方法自动添加参数注释 定义了一个函数,在函数下面敲入了三个双引号后,enter回车并没有自动出现注释,如图: 解决办法 Pycharm中依次打开File —> Settings —> Tools —> Python Integrated Tools,如图&…...
RUST 有哪些整型?
在Rust中,有以下几种整型数据类型: i8 :有符号8位整型,取值范围为-128到127。u8 :无符号8位整型,取值范围为0到255。i16 :有符号16位整型,取值范围为-32768到32767。u16 ࿱…...

【Python 实战】---- 批量识别图片中的文字,存入excel中【使用百度的通用文字识别】
分析 1. 获取信息图片示例 2. 运行实例 3. 运行结果 4. 各个文件的位置 实现 1. 需求分析 识别图片中的文字【采用百度的通用文字识别】;文字筛选,按照分类获取对应的文本;采用 openpyxl 实现将数据存入 excel 中。2. 获取 access_token 获取本地缓存的...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...

visual studio 2022更改主题为深色
visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中,选择 环境 -> 常规 ,将其中的颜色主题改成深色 点击确定,更改完成...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...

家政维修平台实战20:权限设计
目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...
DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”
目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...
Java 二维码
Java 二维码 **技术:**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...

论文笔记——相干体技术在裂缝预测中的应用研究
目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术:基于互相关的相干体技术(Correlation)第二代相干体技术:基于相似的相干体技术(Semblance)基于多道相似的相干体…...

基于 TAPD 进行项目管理
起因 自己写了个小工具,仓库用的Github。之前在用markdown进行需求管理,现在随着功能的增加,感觉有点难以管理了,所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD,需要提供一个企业名新建一个项目&#…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...