[C++] const 成员函数

news2024/11/27 14:46:31

标题:[C++] this指针 & const 成员函数

@水墨不写bug



正文开始:

目录

(一)Cpp的面向对象编程

(二)this指针

(三)const修饰的成员函数


        在正式讲解const修饰成员函数之前,我们先要深入了解几个概念:

(一)Cpp的面向对象编程

        面向对象编程(Object-Oriented Programming,简称OOP)是一种编程范例,它通过将数据和操作数据的方法封装在一起,组成对象,以实现程序的设计和编写。

在C++中,面向对象编程主要包含以下几个概念和特性:

  1. 类(Class):类是面向对象编程的基础,它是一个抽象数据类型,类似于一个模板。它定义了一组属性(成员变量)和操作(成员函数),用于创建对象。类可以看作是对象的模板。

  2. 对象(Object):对象是类的实例化(模板印出来的模子),它是具体的数据实体,具有类定义的属性和行为。对象可以调用类中定义的成员函数来改变其属性或执行一定的操作。

  3. 封装(Encapsulation):封装是将数据和对数据的操作封装在一起,形成一个通过封装,类隐藏了内部的实现细节,只提供一些公共接口(成员函数)来与外部进行交互,从而实现了数据的保护和控制。

  4. 继承(Inheritance):继承是一种创建新类的机制,它允许一个类(子类)继承另一个类(父类)的属性和行为。子类可以继承父类的公共接口,并可以进行扩展或修改。继承可以有效地复用代码,并形成类的层次结构

  5. 多态(Polymorphism):多态是指不同对象对同一消息(方法)作出不同的响应。通过多态,可以在父类的引用或指针中使用子类的对象,实现动态绑定,提高代码的灵活性和可扩展性。

        通过使用类、对象、封装、继承和多态等特性,面向对象编程可以更好地组织和管理代码,使程序的设计更加清晰和易于维护。

        只讲概念很抽象,下面是一个具体的实例Date类: 


class Date
{
public:

	friend ostream& operator<<(ostream& out, const Date d)
    {
	    out << d._year << " " << d._month << " " << d._day;
	    out << endl;
	    return out;
    }
    
    // 获取某年某月的天数
    inline int GetMonthDay(int year, int month)
    {
	    assert(month >= 1 && month <= 12);
	    static int _month[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
	    //如果进入if说明是闰年并且是二月
	    if (month == 2 && ( (year % 4 == 0) && (year % 100 != 0) ) || (year % 400 == 0))
	    {
		    return 29;
	    }
	    else
		    return _month[month];
    }

	// 日期+=天数
	Date& operator+=(int day)
    {
	    if (day < 0)
	    {
	    	(*this) -= (-day);
	    }
	    else
	    {
		    _day += day;
		    while (_day > GetMonthDay(_year, _month))
		    {
			    _day -= GetMonthDay(_year, _month);
			    ++_month;
			    if (_month == 13)
			    {
				    ++_year;
				    _month = 1;
			    }
		    }
	    }
	    return *this;
    }

	// 前置++
	Date& operator++()
    {
	    *this += 1;
	    return *this;
    }

private:
	int _year;
	int _month;
	int _day;
};

         对于这个类,我们可以实例化对象,并且调用对象的成员函数(具体功能):


int main()
{
	Date d1(2024, 5, 9);
    Date d2(2024,6,6);

	d1.operator++();
	cout << d1;

	return 0;
}

        实例化一个对象d1,我们是直接通过 “d1.函数名” 来调用成员函数的, 我们没有在函数中传递任何参数,但是编译器是如何知道是对d1进行操作,而不是对d2进行操作?

        其实,这就涉及到this指针的问题:

(二)this指针

        C++中通过引入this指针解决该问题,即:C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量”的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。

this指针的特性:

        1. this指针的类型:类的类型* const,即成员函数中,this的指向不能被改变。
        2. 只能在“成员函数”的内部使用。
        3. this指针本质上是“成员函数”的形参之一,但是是一个被隐藏了的形参。当对象调用成员函数时,将对象地址作为实参传递给this形参。所以对象中不存储this指针。
        4. this指针是“成员函数”第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递。

 

(三)const修饰的成员函数

        在实现日期类的过程中,我们也许会创建一些只需参照,而不能改变的日期,例如国庆节的日期,暑假的日期等等。

//只读的国庆节日期对象
const Date National_day(2024,10,1);

//只读的暑假日期对象
const Date Summer_vacation(2024,6,20);

但是当我们用这些实例化的对象之后,发现了一些问题:

        一些函数是无法正常调用的!

 

为什么?

        本质是因为权限的放大.导致编译器的函数匹配错误。

        以Date类为例其实,Date类实例化的对象调用的成员函数的this指针的类型是:

Date* const this = ...

        我们创建的const的参照日期对象的类型是:

const Date* const this = ...

        当我们用const修饰的实例化的对象调用普通的成员函数时,由于const修饰的对象是无法修改的,但是传递给普通的成员函数的普通this指针之后,会发现this指针并没有限制*this不能被修改!

 这就是典型的权限的放大问题。解决方法是采用Cpp规定的一个语法:

        解决方法一:在成员函数函数头之后加上一个 “const”;

        普通实例化的对象也可一调用const成员函数,因为经过分析,就会发现其实是权限的缩小。

        解决方法二:再重载一份专门供const对象调用的函数;比较推荐的做法,使写法思路更清晰。

 

总结: 

        将const修饰的“成员函数”称之为const成员函数,const修饰类成员函数,实际修饰该成员函数,隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改。


完~

未经作者同意禁止转载 

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

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

相关文章

实测ChatGPT插件真香用法!视频一键变脑图,高数作业轻松拿捏

Sam Altman诚不我欺&#xff1a; ChatGPT插件和联网功能终于在这两天向尊贵的Plus用户全面开放了。 像之前预告的一样&#xff0c;联网可以直接获取2021年9月之后的消息&#xff0c;插件也安排了70多个&#xff0c;购物订餐订机票等日常功能应有尽有&#xff0c;更专业的数学、…

网站未部署证书有何影响,如何解决?

如果您的网站没有ssl证书会有以下风险 1 浏览器标记为不安全 未安装证书的网站在访问时会有不安全的提示弹窗或者在网址栏直接显示不安全 2 影响企业信誉 当用户访问网站时看到不安全提示&#xff0c;会对网站的真实性和安全性产生怀疑&#xff0c;不敢轻易与该企业合作&…

Python-VBA函数之旅-setattr函数

目录 一、setattr函数的常见应用场景 二、setattr函数使用注意事项 三、如何用好setattr函数&#xff1f; 1、setattr函数&#xff1a; 1-1、Python&#xff1a; 1-2、VBA&#xff1a; 2、推荐阅读&#xff1a; 个人主页&#xff1a; https://blog.csdn.net/ygb_1024?…

宏的优缺点?C++有哪些技术替代宏?(const)权限的平移、缩小

宏的优缺点&#xff1f; 优点&#xff1a; 1.增强代码的复用性。【减少冗余代码】 2.提高性能&#xff0c;提升代码运行效率。 缺点&#xff1a; 1.不方便调试宏。&#xff08;因为预编译阶段进行了替换&#xff09; 2.导致代码可读性差&#xff0c;可维护性差&#xff0…

小阳的戒S笔记

文章目录 写在前面2024年5月8日21:12:172024年5月9日21:48:242024年5月10日08:04:141、记录昨夜之身体变化2、自身制定之计划1.此亦乃要事&#xff0c;特定问了度娘与GPT&#xff0c;找时间还得咨询专业医师。2.通过跑步宣泄&#xff0c;同时锻炼身体3.我不会有压力&#xff0c…

替换spring-boot中的组件版本

spring-boot是一个用于简化开发的框架&#xff0c;引入spring-boot后会自动包含spring框架&#xff0c;通过引入xxx-start来完成指定组件的功能。比如&#xff1a; spring-boot-starter-web(嵌入 Tomcat 和 web 开发需要的 servlet 和 jsp 支持)spring-boot-starter-data-jpa(…

逻辑卷管理-LVM

目录 1. LVM的基本概念 2. Linux下创建和管理LVM 3. 环境准备 4. 物理卷管理 4.1. 创建物理卷 4.2. 显示物理卷 4.3. 删除物理卷 4. 卷组管理 4.1. 创建卷组 4.2. 显示卷组 4.3. 扩展卷组 4.4. 缩减卷组 4.5. 删除卷组 4.6. 分割卷组 4.7 组合卷组 5. 逻辑卷管…

VisualGDB:Linux静态库项目创建、编译及库的使用

接上篇《VisualGDB&#xff1a;Linux动态库项目创建、编译及库的使用》&#xff0c;静态库的创建和使用与动态库基本无差别&#xff0c;唯一需要做的就是指定项目生成静态库。 一、指定项目生成静态库 二、重新构建和编译项目 这里注意&#xff0c;同样要copy一个libxxx.so格式…

InternLM-Chat-7B部署调用-个人记录

一、环境准备 pip install modelscope1.9.5 pip install transformers4.35.2 二、下载模型 import torch from modelscope import snapshot_download, AutoModel, AutoTokenizer import os model_dir snapshot_download(Shanghai_AI_Laboratory/internlm-chat-7b, cache_di…

果味碳酸饮料二氧化碳气容量检测技术的创新与发展

果味碳酸饮料二氧化碳气容量检测技术的创新与发展 一、引言 随着健康饮食理念的普及和消费者对高品质饮料需求的增加&#xff0c;果味碳酸饮料的市场需求日益增长。在这一背景下&#xff0c;如何确保果味碳酸饮料的品质和口感成为了业界关注的焦点。二氧化碳气容量作为影响果味…

数据链路层之 以太网协议

以太网协议 这个协议即规定了数据链路层&#xff0c;同时也规定了物理层的内容。平时使用到的网线&#xff0c;其实也叫做“以太网线”&#xff08;遵守以太网协议的网线&#xff09;。 以太网帧格式 以太网数据帧 帧头 载荷 帧尾。 帧头&#xff1a;目的地址、源地址、类型…

Leetcode—232. 用栈实现队列【简单】

2024每日刷题&#xff08;131&#xff09; Leetcode—232. 用栈实现队列 实现代码 class MyQueue { public:MyQueue() {}void push(int x) {st.push(x);}int pop() {if(show.empty()) {if(empty()) {return -1;} else {int ans show.top();show.pop();return ans;}} else {i…

图像处理(二)

图像处理&#xff08;2&#xff09; 裁剪图片 from skimage import io,dataiimg io.imread(rD:\工坊\图像处理\十个勤天2.png)roiiimg[50:150,120:200,:]io.imshow(roi) 运行结果&#xff1a; 将图片进行二值化 from skimage import io,data,colorimg io.imread(r"…

TPB-1W 系列——1W 3KVDC 隔离 单输出 DC/DC 电源模块

TPB-1W系列产品是专门针对PCB上分布式电源系统中需要与输入电源隔离且输出精度要求较高的电源应用场合而设计。该产品适用于&#xff1b;1&#xff09;输入电源的电压变化≤5%&#xff1b;2&#xff09;输入输出之前要求隔离电压≥3000VDC&#xff1b;3&#xff09;对输出电压稳…

请求响应里面的日期参数

日期参数 需要在控制类使用DateTimeFormat注解 package com.ming.controller; ​ ​ import org.springframework.format.annotation.DateTimeFormat; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.Rest…

【LSTM】LSTM网络及参数学习笔记

图1 LSTM模型结构可视化 [6]. 图2 LSTM cell结构说明 图3 LSTM cell和num_units说明 [4]. 图4 LSTM的网络结构 1. LSTM 是对一个LSTM层的抽象&#xff0c;可以看成是由多个LSTM cell组成&#xff0c;是包含时间步的一个网络 2. LSTM cell 图2是LSTM在时间步上的结构&#xf…

「51媒体」教育论坛会议媒体邀约的资源有哪些

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 中国拥有众多教育方面的媒体资源&#xff0c;这些媒体在邀约时可以用于宣传和推广教育活动、论坛或项目。以下是一些具体的教育媒体邀约资源&#xff1a; 报纸类媒体&#xff1a; 《中…

STM32实现1.8寸液晶屏 LCD SPI串口显示屏模块 TFT彩屏(标准库和HAL库实现)

目录 一、所选模块 液晶模块选择&#xff08;淘宝上均有售卖&#xff09; 模块引脚 二、嵌入式单片机型号 三、接线表设计 四、开发环境版本说明 五、标准库实现 六、HAL库实现 七、完整工程&#xff08;内含标准库和HAL库源码&#xff09; 代码链接 一、所选模块 液…

OpenSSL实现AES的ECB和CBC加解密,可一次性加解密任意长度的明文字符串或字节流(QT C++环境)

本篇博文讲述如何在Qt C的环境中使用OpenSSL实现AES-ECB/CBC-Pkcs7加/解密&#xff0c;可以一次性加解密一个任意长度的明文字符串或者字节流&#xff0c;但不适合分段读取加解密的&#xff08;例如&#xff0c;一个4GB的大型文件需要加解密&#xff0c;要分段读取&#xff0c;…

Android system property运作流程源码分析

一.序 前文分析了build.prop这个系统属性文件的生成&#xff0c;每个属性都有一个名称和值&#xff0c;他们都是字符串格式。属性被大量使用在Android系统中&#xff0c;用来记录系统设置或进程之间的信息交换。属性是在整个系统中全局可见的。每个进程可以get/set属性&#x…