C++类和对象_02----对象模型和this指针

news2025/2/25 15:10:11

目录

  • C++对象模型和this指针
    • 1、成员变量和成员函数分开存储
      • 1.1、空类大小
      • 1.2、非空类大小
      • 1.3、结论
    • 2、this指针概念
      • 2.1、解决名称冲突
      • 2.2、在类的非静态成员函数中返回对象本身,可使用return *this
      • 2.3、拷贝构造函数返回值为引用的时候,可进行链式编程
    • 3、空指针访问成员函数
      • 3.1、访问ShowClassName()成员函数
      • 3.2、访问ShowPeopleAge()成员函数
    • 4、const修饰成员函数
      • 4.1、常函数
        • 4.1.1、 常函数本质是对this指针的修改
        • 4.1.2、成员属性声明时加关键字mutable后,可在常函数中修改
      • 4.2、常对象

C++对象模型和this指针

1、成员变量和成员函数分开存储

在C++中,类内的成员变量和成员函数分开存储
只有非静态成员变量才属于类的对象上

1.1、空类大小

class MyPeople
{
};
void Class_Func_Constructor_Member()
{
    MyPeople p1;
    cout << "空对象占用的内存空间为: " << sizeof(p1) << " 字节"<< endl;
}

运行结果:
在这里插入图片描述

C++ 会为每个空对象分配一个字节的内存空间,是为了区分空对象占内存的位置。每个空对象都有一个独一无二的地址

1.2、非空类大小

class MyPeople07
{
public:
    int m_a;//非静态成员变量,属于类的对象上,计算类对象大小时需要计算

    static int m_b;//静态成员变量,不属于类的对象上,计算类对象大小时不需要计算

    void func()  //非静态成员函数,不属于类的对象上 ,计算类对象大小时不需要计算
    {

    }

    static void func2()  //静态成员函数,不属于类的对象上 ,计算类对象大小时不需要计算
    {

    }

};
void Class_Func_Constructor_Member()
{
    MyPeople07 p2;
    cout << "非空对象占用的内存空间为: " << sizeof(p2) << " 字节" << endl;
}

运行结果:
在这里插入图片描述

1.3、结论

由此可知,在类中,只有非静态成员变量才属于类的对象上,在计算类对象大小时,只需要考虑非静态成员变量的种类和个数。

2、this指针概念

在C++中成员变量和成员函数是分开存储的。每一个非静态成员函数只会诞生一份函数实例,也就是说多个同类型的对象会共用一块代码

问题:这一块代码是如何区分那个对象调用自己的呢?
c++通过提供特殊的对象指针,this指针,解决上述问题。
(1)this指针指向被调用的成员函数所属的对象
(2)this指针是隐含每一个非静态成员函数内的一种指针
(3)this指针不需要定义,直接使用即可

this指针的用途:
(1)当形参和成员变量同名时,可用this指针来区分。解决名称冲突
(2)在类的非静态成员函数中返回对象本身,可使用return

2.1、解决名称冲突

当形参和成员变量同名时,可用this指针来区分
this指针 指向 被调用的成员函数 所属的对象

class MyPeople08
{
public:
    MyPeople08(int age)
    {
        this->age = age;

    }
   int age;
};
void Class_Func_Constructor_this_ptr()
{
    //解决名称冲突
    MyPeople08 p1(10);
    cout << "p1 AGE : " << p1.age << endl;
}

运行结果:
在这里插入图片描述

2.2、在类的非静态成员函数中返回对象本身,可使用return *this

class MyPeople09
{
public:
    MyPeople09(int age)
    {
        this->age = age;
    }
    MyPeople09& PeopleAddAge(MyPeople09 &p)
    {
        this->age += p.age;
       
        return *this; //this 是指向对象的指针,*this就是对象本身
    }
   int age;
};
void Class_Func_Constructor_this_ptr()
{
    //返回对象本身用 *this
    MyPeople09 p1(10);
    cout << "p1 AGE : " << p1.age << endl;
    
    MyPeople09 p2;
    p2.PeopleAddAge(p1);
    cout << "p2 AGE : " << p2.age << endl;
}

运行结果:
在这里插入图片描述

2.3、拷贝构造函数返回值为引用的时候,可进行链式编程

class MyPeople08
{
public:
    MyPeople08(int age)
    {
        this->age = age;
    }

    MyPeople08& PeopleAddAge(MyPeople08 &p)
    {
        this->age += p.age;
        return *this;
    }

    int age;
};
void Class_Func_Constructor_this_ptr()
{
    MyPeople08 p1(10);
    cout << "p1 AGE : " << p1.age << endl;

    MyPeople08 p2(10);
    cout << "p2 AGE : " << p2.age << endl;

    //链式调用
    p2.PeopleAddAge(p1).PeopleAddAge(p1).PeopleAddAge(p1);
    cout << "链式调用后 p2 AGE : " << p2.age << endl;
}

运行结果:
在这里插入图片描述

注意:当拷贝构造函数返回值为类名时,结果如下
在这里插入图片描述

原因:
MyPeople08 对象 作为返回值会触发编译器提供的浅拷贝返回的对象跟原来的对象不是同一块内存
MyPeople08 & 对象 作为返回值,那么接收的变量就是原来对象的一个别名,操纵同一块内存
链式调用目的是 在原数据改变的基础上 递增 ,引用是地址传递 会改变原有的值,不用引用就变成复制操作了

3、空指针访问成员函数

class MyPeople09
{
public:
    void ShowClassName()
    {
        cout << "This is MyPeople09 class !" << endl;
    }

    void ShowPeopleAge()
    {
        cout << "age = " << this->m_Age << endl;
    }

    int m_Age;
};

3.1、访问ShowClassName()成员函数

void Class_Func_Constructor_nullptr_func()
{
    MyPeople09 *p1 = NULL;
    p1->ShowClassName();
}

运行结果:
在这里插入图片描述

3.2、访问ShowPeopleAge()成员函数

void Class_Func_Constructor_nullptr_func()
{
    MyPeople09 *p1 = NULL;
    p1->ShowPeopleAge();
}

报错!!!
在这里插入图片描述
因为对于传入的指针为NULL函数来说,
其中的 cout << "age = " << m_Age << endl;相当于 cout << "age = " << this->m_Age << endl; 默认会自动加上this指针
此时,调用该函数时,传入的指针为NULL,再通过NULL->m_Age访问,就会出现问题。

修改方式如下:
在传入的指针为NULL函数中增加对空指针的判断即可

 void ShowPeopleAge()
    {
        //解决方式:增加对空指针的判断
        if (this == NULL)
        {
            return;
        }
        cout << "age = " << this->m_Age << endl;
    }

4、const修饰成员函数

4.1、常函数

成员函数后加const后我们称为这个函数为常函数

特性:
1、常函数内不可以修改成员属性
2、成员属性声明时加关键字mutable后,在常函数中依然可以修改

4.1.1、 常函数本质是对this指针的修改

this指针的本质是一个 “指针常量”( MyPeople10 * const this ),表示:指针的指向不可修改;
在常函数中,该指针被进一步限定为 : const MyPeople10 * const this 表示:指针的指向不可修改并且指向的内容不能被修改。
此时,如果通过this指针修改成员变量的值,编译器会报错:不可修改的左值。如图:
在这里插入图片描述

4.1.2、成员属性声明时加关键字mutable后,可在常函数中修改

在这里插入图片描述

4.2、常对象

声明对象前加const 称该对象为 常对象

void Class_Func_Constructor_const_func()
{
    const MyPeople10 p1; 	//在对象前加 const 即为 常对象
    //p1.m_A = 123;  		//不可修改普通成员变量
    p1.m_B = 789;        	//mutable特殊变量,在常对象中可以修改值

    p1.ShowMyPeople10Class();  //常对象只能调用常函数
    p1.func();  //
}

常对象只能调用常函数
在这里插入图片描述

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

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

相关文章

Python加密算法种类以及开发场景中的运用

不用说火爆一时&#xff0c;全网热议的Web3.0区块链技术&#xff0c;也不必说诸如微信支付、支付宝支付等人们几乎每天都要使用的线上支付业务&#xff0c;单是一个简简单单的注册/登录功能&#xff0c;也和加密技术脱不了干系&#xff0c;本次我们耙梳各种经典的加密算法&…

【RecBole-GNN/源码】RecBole-GNN中lightGCN源码解析

如果觉得我的分享有一定帮助&#xff0c;欢迎关注我的微信公众号 “码农的科研笔记”&#xff0c;了解更多我的算法和代码学习总结记录。或者点击链接扫码关注【RecBole-GNN/源码】RecBole-GNN中lightGCN源码解析 【RecBole-GNN/源码】RecBole-GNN中lightGCN源码解析 原文&…

【C++】初识CC++内存管理

前言 我们都知道C&C是非常注重性能的语言&#xff0c;因此对于C&C的内存管理是每一个C/C学习者必须重点掌握的内容&#xff0c;本章我们并不是深入讲解C&C内存管理&#xff0c;而是介绍C&C内存管理的基础知识&#xff0c;为我们以后深入理解C&C内存管理做铺…

基于 U-Net 网络的遥感图像语义分割 完整代码+论文

一、研究目的U-Net 是一种由全卷积神经网络启发的对称结构网络&#xff0c;在医疗影像分割领域取得了很好的效果。 此次研究尝试使用 U-Net 网络在对多光谱遥感影像数据集上进行训练&#xff0c;尝试使用卷积神经网络自动分割出建筑&#xff0c;希望能够得到一种自动分割遥感影…

ElementUI分页的实现

官网地址&#xff1a;Element - The worlds most popular Vue UI framework 第一步&#xff1a;拷贝你喜欢的分页类型放在你的组件页面需要用到的分页位置 <el-paginationsize-change"handleSizeChange"current-change"handleCurrentChange":current-p…

1.JAVA-JDK安装

前言&#xff1a;工具下载地址阿里云盘&#xff1a;Java-Jdk&#xff1a;https://www.aliyundrive.com/s/JpV55xhVq2A提取码: j53y一、jdk下载&#xff1a;前往Oracle官网可免费下载地址&#xff1a;https://www.oracle.com/java/technologies/downloads/ 此处我下载的是jdk8&a…

【nas折腾篇】抉择吧,是入门还是放弃

2018年公司一位女同事问群晖的nas是否值得买。我一脸懵&#xff0c;以前给公司买云服务有采购nas盘&#xff0c;直接mount挂到服务器上当存储&#xff0c;但对于单独的nas服务器没有什么概念。一晃几年过去了&#xff0c;陆续刷到些nas服务的视频&#xff0c;周边朋友用nas的也…

nginx的介绍及源码安装

文章目录前言一、nginx介绍二、nginx应用场合三、nginx的源码安装过程1.下载源码包2.安装依赖性-安装nginx-创建软连接-启动服务-关闭服务3.创建nginx服务启动脚本4.本实验---纯代码过程前言 高可用&#xff1a;高可用(High availability,缩写为 HA),是指系统无中断地执行其功…

OSI七层模型与物理层与设备链路层

目录 协议 举例 OSI七层模型 理解七层模型 以下为OSI七层模型数据逐层封装和数据逐层解封的过程 TCP/IP参考模型 数据包的层层封装与层层拆包 各层的数据以及协议 封装所用的协议的数字表示形式 物理层 模拟信号 模拟信号特点 数字信号 数字信号特点 数据通信模…

【存储】etcd的存储是如何实现的(3)-blotdb

前两篇分别介绍了etcd的存储模块以及mvcc模块。在存储模块中&#xff0c;提到了etcd kv存储backend是基于boltdb实现的&#xff0c;其在boltdb的基础上封装了读写事务&#xff0c;通过内存缓存批量将事务刷盘&#xff0c;提升整体的写入性能。botldb是etcd的真正的底层存储。本…

CSS预处理器sass和less

文章目录CSS预处理器什么是CSS预处理器Sass和LESS背景介绍Sass背景介绍LESS的背景介绍Sass安装Sass下载Ruby安装文件安装Ruby安装Sass编译Sass命令行编译命令行编译配置选项四种编译排版演示nested 编译排版格式expanded 编译排版格式compact 编译排版格式compressed 编译排版格…

Ethernet-APL——过程自动化的新黄金标准

| Ethernet-APL为终客户和设备制造商带来益处 Ethernet-APL&#xff08;Advanced Physical Layer&#xff0c;高级物理层&#xff09;是一种两线制以太网物理层&#xff0c;它使用了由IEEE 802.3cg所定义的10BASE-T1L&#xff0c;并采用了新的工艺制造规定&#xff0c;因此构成…

2.21多线程

一.并发编程java实现并发编程的方式是多线程其他语言,主打的 并发编程并不一样Go 主要通过多协程的方式实现并发erlang 是通过actor模型实现并发JS 通过定时器和事件回调的方式实现并发二.多线程在java标准库,提供了一个Thread类,表示/操作线程Thread类可以视为Java标准库提供的…

CCNP350-401学习笔记(401-450题)

401、What is the function of vBond in a Cisco SDWAN deployment? A. initiating connections with SD-WAN routers automatically B. pushing of configuration toward SD-WAN routersC. onboarding of SDWAN routers into the SD-WAN overlay D. gathering telemetry dat…

易点天下基于 StarRocks 全面构建实时离线一体的湖仓方案

作者&#xff1a;易点天下数据平台团队易点天下是一家技术驱动发展的企业国际化智能营销服务公司&#xff0c;致力于为客户提供全球营销推广服务&#xff0c;通过效果营销、品牌塑造、垂直行业解决方案等一体化服务&#xff0c;帮助企业在全球范围内高效地获取用户、提升品牌知…

yolov5源码解读--训练策略

yolov5源码解读--训练策略超参数解读命令行参数train模型迭代测试超参数解读 hyp.scratch.yaml lr0: 0.0032 初始学习率 lrf: 0.12 使用余弦函数动态降低学习率(lr0*lrf) momentum: 0.843 动量 weight_decay: 0.00036 权重衰减项 warmup_epochs: 2.0 预热&#xf…

详解Unicode字符集以及字符编码实现(一)

在日常生活中&#xff0c;我们经常会碰到打开一个文件&#xff0c;但是文件内容乱码的问题&#xff0c;比如我想看《西游记》这部小说。 下载链接&#xff1a;https://m.ijjjxs.com/txt/dl-35-12585.html 点击TXT电子书下载&#xff0c;很快就会下载完成&#xff0c;但是使用…

【测试面试】自我分析+功能+接口自动化+性能测试面试题(大全),知己知彼百战百胜......

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 分析自己和面试企业…

mac tcpdump学习

学习原因 工作上遇到了重启wifi后无法发出mDNS packet的情况&#xff0c;琢磨一下用tcpdump用的命令如下 sudo tcpdump -n -k -s 0 -i en0 -w VENDOR-DUT-INTERFACE.pcapng是在测airplay BCT认证时&#xff0c;官方文档的解决方法。对tcpdump很不了解&#xff0c;现汇总如下的学…

JS中数组如何去重(ES6新增的Set集合类型)+经典two sum面试题

现在有这么一个重复数组&#xff1a;const arr [a,a,b,a,b,c]只推荐简单高效的方法&#xff0c;复杂繁琐的方法不做推荐方法一&#xff1a;const res [...new Set(arr)]Set类型是什么呢&#xff1f;Set 是ES6新增的一种新集合类型。具体知识点可以看下面附录&#xff1a;根据…