const修饰的成员函数

欢迎来到博主的专栏——C++杂谈
博主ID:代码小豪

文章目录

    • const修饰了什么
    • const修饰的成员函数是为什么?
    • 问答环节

const修饰的成员函数并非是在返回值类型用const,而是在成员函数的末尾加上const,比如:

const char& operator[](size_t pos) const;

我们先忽略这个函数的定义是什么,只需要知道一个事情,这个operator []函数是一个成员函数,并且是一个const修饰的成员函数(只有成员函数才能末尾加上const修饰)。

如果你是一个刚从c语言学完过来学c++的人,如果看到这么一个函数声明,我想大概都是一脸懵逼的,因为这个设定有点反直觉了,在C语言当中,const总是放在函数名或变量名的前面起到修饰作用。

那么为什么c++会有这么一个设计呢?这就不得不提到c++的封装这一特性了。

const修饰了什么

const修饰成员函数到底修饰了什么?它的后面并不存在任何标识符。所以不熟悉c++的人初见这个const当然是一头雾水(博主也是)。

这就得说到c++类的封装特性了。在定义的成员函数当中,该成员函数的实际参数并非我们所声明的那样,比如上例中的operator []成员函数,看起来只声明了一个pos参数。实际上所有的成员函数都有一个隐藏的参数,c++称为this指针。

c++规定,this指针不能显示的声明在成员函数当中。所有的成员函数都会存在一个this指针。虽然this指针不能在参数列表当中声明,但我们可以在函数体内使用this指针。

message& operator =(const message& mes)
{
	this->_text = mes._text;
	return *this;
}

this指针是指向调用此函数成员的对象的指针。其类型为object* const this,this指针存在const修饰,因此在成员函数当中对this的指向进行修改是一个非法的操作。

message& operator =(const message& mes)
	{
		this->_text = mes._text;
		this = nullptr;//error,this指针不能被修改
		return *this;
	}

那么问题来了,虽然我们不能修改this指针,但是可以修改this指针指向的数据(*this)。如果我们声明了一个const类型的对象,那么在这个const对象的this指针就应该是这种类型。const object* const this

在c++中存在权限这一概念,如果一个函数的参数是非const引用或指针类型,那么const的指针或引用参数就不能调用这个函数。我们将其称为c++当中禁止权限的放大

如何理解这个权限的放大呢?我们拿一个例子举例。比如某个函数的参数是非const类型的引用,而实参缺上传了一个const类型,那么这个非const的引用就能对const类型的对象进行修改,这个对象在设计就确定不能被修改,但是通过某个函数缺将该对象修改了,这被称为权限的放大。在c++中是禁止的。

c++允许权限的缩小,禁止权限的放大,一个非const引用不能指向const对象,但是const引用可以指向非const对象

	const int a = 0;
	int& ra = a;//error,权限的放大。
	int b = 10;
	const int& rb = b;//ok,权限的缩小

让我们回到this指针,我们说到非const的对象的this指针的类型是object* const this,而const对象的this指针的类型是const object* const this

而一般的成员函数中的this指针是object* const this,因此一般的成员函数是不能作用与const对象的。因此我们需要将成员函数的隐藏参数this指针的类型修改为const object* const this,但是我们不能再参数列表当中显示的将this指针声明为const object* const this。因此c++允许我们将const放在成员函数的后面,将this指针声明为const object* const this。

	char& operator[](size_t pos)//object*const this

	const char& operator[](size_t pos) const//const object*const this

  • const修饰的成员函数的this指针是const object* const this
  • 非const的成员函数this指针是object* const this

const修饰的成员函数是为什么?

前面已经讲完了const修饰的成员函数,其const修饰的不是函数的返回值,也不是参数列表中的参数。而是成员函数当中的this指针,使其函数能作用于const对象。

那么const修饰成员函数的目的是什么呢?

  • 只有const修饰的成员函数才能作用与const对象身上
  • 能让class接口更加易于理解。函数的使用者可以轻松的得知哪些函数可以改动对象的内容(非const成员函数),哪些函数不会修改对象的内容(const成员函数)。
  • 它们使操作const对象变得灵活(如果一个类定义出来的const对象不能被使用,那么这个类就少了不少的用法)

还有一个很重要的特性。如果两个成员函数是const修饰和非const修饰的,那么这两个函数可以重载。我们看看下面这个类。

class message
{
public:
	message(const char* str)
	{
		_text = str;
	}
	char& operator[](size_t pos)//object*const this
	{
		return _text[pos];
	}
	const char& operator[](size_t pos) const//const object*const this
	{
		return _text[pos];
	}

private:
	std::string _text;
};

message的operator []可以被这么使用。

	message text1("hello world");
	cout << text1[1];//调用的是非const版本的operator []
	
	const message text2("hello world");
	cout << text2[2];//调用的是const版本的operator []

重载operator[]还有一个好处。只要给予operator[]不同的返回类型,就可以让const message对象和非const message对象进行不同的处理。

	message text1("hello world");
	text1[1] = 'j';//ok,修改了一个char类型的引用
	cout << text1[1];//ok,返回的是char类型的引用字符
	
	const message text2("hello world");
	text2[2] = 'j';//error,对const char类型的引用进行修改
	cout << text2[2];//ok,返回的是const char类型的字符

注意,会造成这种差异的原因是operator []的返回类型所致。错误的原因是因为一个对const char&的变量进行赋值操作。

问答环节

问:为什么需要将一个成员函数重载成const版本和非const版本?

答:

  • 这是由于某些成员函数要考虑到const对象和非const对象调用时造成的不同影响。比如非const对象可以被修改,而const对象不可被修改。除外。c++存在这么一个特性:const修饰的成员函数可以接收const类型的对象的this指针和非const类型的对象的this指针,而非const修饰的成员函数不能接收const类型的对象的this指针。(禁止权限的放大)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

YOLOv9改进策略 | 添加注意力篇 | 一文带你改进GAM、CBAM、CA、ECA等通道注意力机制和多头注意力机制

一、本文介绍 这篇文章给大家带来的改进机制是一个汇总篇&#xff0c;包含一些简单的注意力机制&#xff0c;本来一直不想发这些内容的&#xff08;网上教程太多了&#xff0c;发出来增加文章数量也没什么意义&#xff09;&#xff0c;但是群内的读者很多都问我这些机制所以单…

CUDA调整指令级原语

在GPU上运行的运算密集型应用程序&#xff0c;处理器的计算吞吐量可以用它在一段时间内执行操作的数量来衡量。因为GPU有很多SIMT指令和计算核心&#xff0c;所以其峰值计算吞吐量通常比其他的处理器高。 对应用程序的吞吐量和正确性进行优化时&#xff0c;理解不同低级原语的…

SOCKET编程(1):基本概念

基本概念 socket分类 socket提供了**流(stream)和数据报(datagram)**两种通信机制&#xff0c;即流socket和数据报socket 流socket基于TCP协议&#xff0c;是一个有序、可靠、双向字节流的通道&#xff0c;传输数据不会丢失、不会重复、顺序也不会错乱 数据报socket基于UDP…

子查询之一(单行子查询, 多行子查询)

1. 子查询 子查询是指一个查询语句嵌套在另一个查询语句内部的查询.这个特性在MySQL4.1开始引入. SQL中子查询的使用大大增强了SELECT查询的能力.因为很多时候查询需要从结果集中获取数据&#xff0c;或者需要从同一个表中先计算得到一个数据结果&#xff0c;然后与这个数据结…

在Windows中创建和管理组策略管理模板的中央存储

本文参考于&#xff1a; 创建和管理中央存储 - Windows Client | Microsoft Learn 管理模板文件存储 Windows使用中央存储来存储管理模板&#xff0c;与组策略不同&#xff0c;ADM文件夹并不是通过组策略对象&#xff08;GPO&#xff09;来创建的。由于Windows版本与Windows…

OpenAI 发布 AI 生成图片检测器;Meta 推出 AI 广告创意工具;Google 正式发布 Pixel 8a,主打 AI

OpenAI 发布 AI 生成图片检测器 OpenAI 昨日官宣推出专用的 AI 监测工具&#xff0c;用于监测图片是否由其旗下 AI 图片生成工具 DALL-E 生成&#xff0c;准确率高达 98.8%。 不过该公司表示&#xff0c;这个检测工具并非旨在检测 Midjourney 和 Stability 等其他流行生成器生…

Java基于Spring Boot框架毕业生实习与就业管理系统的设计与实现(附源码,说明文档)

博主介绍&#xff1a;✌IT徐师兄、7年大厂程序员经历。全网粉丝15W、csdn博客专家、掘金/华为云//InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3…

vue+springboot实现excel批量数据的导入导出

①后端配置端口&#xff1a;修改UserController UserController&#xff1a; package com.example.springboot.controller;import cn.hutool.core.util.StrUtil; import cn.hutool.poi.excel.ExcelReader; import cn.hutool.poi.excel.ExcelUtil; import cn.hutool.poi.excel.…

IPFoxy Tips:什么是静态住宅IP?静态ISP代理指南

静态住宅代理&#xff08;也称为静态ISP代理&#xff09;是最流行的代理类型之一。它们也是隐藏您的身份并保持在线匿名的最佳方法之一。您为什么要使用住宅代理而不是仅使用常规代理服务&#xff1f;下面我具体分享。 一、什么是静态住宅代理&#xff1f; 首先&#xff0c;我…

Pentaho Community Edition 下载安装和运行

1 访问网站 https://www.hitachivantara.com/pentaho/pentaho-plus-platform/data-integration-analytics/pentaho-community-edition.html &#xff0c;点击 Download Now 。 2 选中&#xff0c;然后点击 Proceed to Download。 3 页面往下滑&#xff0c;选择合适的版本&…

关于线程池,它的扩展问题你知道吗?(自己总结)

专门想一下为什么线程池不用Excutors&#xff0c;之前的印象是错的&#xff0c;居然还拿来面试里讲&#xff0c;惭愧&#xff0c;这里暂时整理俩小问题&#xff0c;其他的后续可能会更新。。 线程池是创建的越大越好嘛 #线程池创建的越大越好吗 Tip&#xff1a;2024-04-10 更…

YOLOv5-7.0改进(三)添加损失函数EIoU、AlphaIoU、SIoU、WIoU、MPDIoU、NWD

前言 损失函数的改进一直是涨点的重要技巧&#xff0c;本篇博客将使用六个不同损失函数对算法进行改进&#xff0c;并绘制出改进结果对比图~ 往期回顾 YOLOv5-7.0改进&#xff08;一&#xff09;MobileNetv3替换主干网络 YOLOv5-7.0改进&#xff08;二&#xff09;BiFPN替换…

SRC上分秘诀+实战挖掘+挖洞技巧+新手上路+详细讲解

SRC马上到来 可能有些好兄弟们还没有头绪 只会做一些靶场 并没有什么实战经验 所以这篇文章给大家分享一下我挖洞2个月的经验分享 适合新手上路 如何找站&#xff1f; 谷歌搜索 谷歌搜索 谷歌搜索 SQL注入XSS所有漏洞 inurl:.php?idxx 公司inurl:.asp?idxx 公司inurl:.jsp?…

【每日刷题】Day35

【每日刷题】Day35 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c; 1. 844. 比较含退格的字符串 - 力扣&#xff08;LeetCode&#xff09; 2. 2487. 从链表中移除节点 - 力…

C++:编程界的王者,引领未来的创新之路

在编程语言的浩瀚星空中&#xff0c;C犹如一颗耀眼的恒星&#xff0c;以其卓越的性能、深厚的底蕴和广泛的应用领域&#xff0c;持续引领着编程界的发展。它不仅在当下拥有无可替代的地位&#xff0c;更在未来展现出无限的潜力和可能性。 一、C&#xff1a;编程界的王者风范 …

[Linux深度学习笔记5.9]

5.9笔记 DNS: 软硬链接&#xff1a; 软链接&#xff1a; 软链接&#xff1a;ln -s /源文件 /目标位置/链接名称》创建软链接1.既可以对目录使用&#xff0c;也可以对文件使用2.删除源文件&#xff0c;软链接不可用3.软链接可以跨文件系统使用4.源文件和软链接的inode号不同5.…

【springboot基础】如何搭建一个web项目?

正在学习springboot&#xff0c;还是小白&#xff0c;今天分享一下如何搭建一个简单的springboot的web项目&#xff0c;只要写一个类就能实现最基础的前后端交互&#xff0c;实现web版helloworld &#xff0c;哈哈&#xff0c;虽然十分简陋&#xff0c;但也希望对你理解web运作…

MGRE 实验

需求&#xff1a;1、R2为ISP&#xff0c;其上只能配置IP地址。 2、R1-R2之间为HDLC封装 3、R2-R3之间为ppp封装&#xff0c;pap认证&#xff0c;R2为主认证方。 4、R2-R4之间为ppp封装&#xff0c;chap认证&#xff0c;R2为主认证方。 5、R1、R2、R3构建MGRE环境&#xff0…

C++语言·string类

1. 为什么有string类 C语言中&#xff0c;字符串是以\0结尾的一些字符的集合&#xff0c;为了操作方便&#xff0c;C标准库中提供了一些str系列的库函数(strcpy,strcat)&#xff0c;但是这些库函数与字符串是分离开的&#xff0c;不太符合OOP(Object Oriented Programming面向对…

ARM(4)缓存一致性

目录 一、缓存一致性问题 二、一致性实现方案 2.1 目录一致性协议 2.2 嗅探一致性协议 三、CHI协议 3.1 cache state 3.2 snoop维护一致性 四、其他一致性协议 4.1 MSI协议 4.2 MESI 协议 4.3 MOESI协议 本文介绍以下内容&#xff1a; 缓存一致性问题一致性实现方案…
最新文章