【C++】const成员 | 取地址运算符重载

Ⅰ. const成员

两种const

我们知道,用const修饰 能起到保护,使之不被修改的作用。

修饰指针的const有两种位置:

我们学过的this指针,就被后者所修饰,因此无法被修改。

const成员函数

➡️为了保护函数里的成员,使不被修改,C++引入了const成员函数。

“const成员函数” ,就是被const修饰的成员函数。

const的存在,使我们不能对任何成员进行修改。

➡️它长这样:

void Date::Print() const
{……
}

这个函数相当于:

void Date::Print(const Date* const this)
{……
}

❗注意:前后两个const的意义是不一样的。

前者修饰*this,保护 this指向的空间的内容 不被修改。

后者修饰this,保护this指针不被修改。

❓🤔这个const的位置好怪啊,为啥要放在最末尾?而不是开头?

const:爷就长得怪,咋地!

不能放开头啊,那样const就成修饰返回值的了。

➡️对比this指针的类型:

普通函数:类型* const

const成员函数:const 类型* const

➡️权限问题:

就像公司上下级关系,权限大的可以调用权限小的;

而权限小的不可以调用权限大的。

解释这张图:

被const修饰的Print() / d2,因为被限制了内容不能修改,所以权限相对更低。

未被const修饰的Print() / d1,可被修改,自由度更高,权限相对更高。

彼此的关系就用上下级、平级的关系来理解。

所以,const成员函数内部 不可调用 其他非const成员函数;

而非const……可调用……const……。

➡️什么时候加const?

如果一个函数不用修改,性质是只读的,那就加上const来保护。

如果其性质是可读可写,那就不能加。

Ⅱ. 取地址运算符重载

先亮身份:类的六大默认成员函数之一。

函数名:operator&

作用:自定义类型的取地址

引入

来看这个例子。我们知道,自定义类型的运算 需要我们自己去实现 运算符重载,运算符&同样如此。

而这里,我们没写operator&,那究竟能否取地址成功呢?

class Date {
public:Date(int year = 1900, int month = 1, int day = 1) {_year = year;_month = month;_day = day;}
private:int _year;int _month;int _day;
};
​
int main() {
​Date d1(2000, 1, 1);cout << &d1 << endl;   //前面没写operator&//能否取地址成功呢?return 0;
}

结果:

 

取地址成功!

❓But why?

💡这是因为,C++很贴心地将 取地址运算符重载 纳入默认成员函数。

也就是说,operator& 和前几位默认成员函数的福利一样:

如果我们写了,编译器会自动调用;

如果没写,编译器会自动生成,并自动调用。

❓取地址运算符重载长啥样?

Here comes the model:

Date* operator&()
{return this;
}

取地址运算符重载分两种:

1.& 普通对象

2.& const修饰的对象

普通对象取地址

很easy,不详讲了。我们来手动实现一下:

class Date {
public:Date(int year = 1900, int month = 1, int day = 1) {_year = year;_month = month;_day = day;}
​Date* operator&() {return this;    //this就是它的地址}
​
private:int _year;int _month;int _day;
};
​
int main() {Date d1(2000, 1, 1);cout << &d1 << endl;
​return 0;
}

const对象取地址

当对象被const修饰时,会特殊一些。

来看d1和d2的对比:

class Date {
public:Date(int year = 1900, int month = 1, int day = 1) {_year = year;_month = month;_day = day;}void Print(){printf("%d-%d-%d\n", this->_year, this->_month, this->_day);}
​
private:int _year;int _month;int _day;
};
​
int main() {Date d1(2000, 1, 1);      //普通对象d1d1.Print();
​const Date d2(2077,1,1);  //被const修饰的对象d2d2.Print();
​return 0;
}

然而,压根编译不过去:

普通对象d1没问题,而const修饰的d2却亮红牌了,为啥?

其实,const成员报错的原因往往是🤔……权限的放大!

来分析下:

Print函数中,this指针的类型是:Date* const

而d2的类型是:const Date* const

所以说,d2去调用Print(),是一次权限的放大!是以下犯上,大逆不道!

💡对此,解决方案是:

const修饰的对象,应调用const取地址运算符重载

即,d2应调用:

void  Print() const{printf("%d-%d-%d\n", this->_year, this->_month, this->_day);
}

什么时候要手动实现operator& ?

我们尽可放宽心,即使是const对象,编译器仍会自动生成 相应的const operator&。

所以无论是 普通对象 还是 const对象 取地址,我们都无需手动实现operator&。

大部分情况下,取地址运算符重载都不用自己写,编译器默认生成的就够用了。

只有特殊情况才需要重载,

如:你不希望别人取到你的地址。那这时就:

Date* operator&(){return nullptr;
}

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

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

相关文章

《Java极简设计模式》第05章:原型模式(Prototype)

作者&#xff1a;冰河 星球&#xff1a;http://m6z.cn/6aeFbs 博客&#xff1a;https://binghe.gitcode.host 文章汇总&#xff1a;https://binghe.gitcode.host/md/all/all.html 源码地址&#xff1a;https://github.com/binghe001/java-simple-design-patterns/tree/master/j…

【日常积累】Linux下sftp搭建

概述 SFTP是Secure File Transfer Protocol的缩写&#xff0c;是安全文件传送协议。可以为传输文件提供一种安全的加密方法。跟ftp几乎语法功能一样。 SFTP是SSH的一部分&#xff0c;是一种传输档案至Blogger伺服器的安全方式。它本身没有单独的守护进程&#xff0c;必须使用s…

Elasticsearch 8.X reindex 源码剖析及提速指南

1、reindex 源码在线地址 为方便大家验证&#xff0c;这里给出 reindex github 源码地址。 https://github.com/elastic/elasticsearch/blob/001fcfb931454d760dbccff9f4d1b8d113f8708c/server/src/main/java/org/elasticsearch/index/reindex/ReindexRequest.java reindex 常见…

开源软件的崛起:历史与未来

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

Lambda函数

一.概念 1.利用lambda表达式可以编写内嵌的匿名函数&#xff0c;用以替换独立函数或者函数对象 2.每当你定义一个lambda表达式后&#xff0c;编译器会自动生成一个匿名类&#xff08;这个类当前重载了&#xff08;&#xff09;运算符&#xff09;&#xff0c;我们称为闭包类型…

8.6 【C语言】返回指针值的函数

一个函数可以返回一个整型值、字符值、实型值等&#xff0c;也可以返回指针型的数据&#xff0c;即地址。 类型名 *类型名&#xff08;参数表列&#xff09; 例8.25 有a个学生&#xff0c;每个学生有b门课程的成绩。要求在用户输入学生序号以后&#xff0c;能输出该学生的全部…

Lazada商品详情接口 获取Lazada商品详情数据 Lazada商品价格接

一、引言 随着电子商务的迅速发展和普及&#xff0c;电商平台之间的竞争也日趋激烈。为了提供更好的用户体验和更高效的后端管理&#xff0c;Lazada作为东南亚最大的电商平台之一&#xff0c;开发了一种商品详情接口&#xff08;Product Detail API&#xff09;。该接口允许第…

数据可视化是什么?有什么工具?

一、什么是数据可视化&#xff1f; 数据可视化是一种通过图表、图形、地图和其他视觉元素将数据呈现给用户的方式。它是将复杂的数据转化为易于理解和解释的视觉形式的过程。数据可视化旨在帮助用户发现数据中的模式、趋势和关联&#xff0c;并从中获得洞察力。 数据可视化的…

根据源码,模拟实现 RabbitMQ - 转发规则实现(6)

目录 一、转发规则实现 1.1、需求分析 1.2、实现 Router 转发规则 1.2.1、bindingKey 和 routingKey 参数校验 1.2.2、消息匹配规则 1.2.3、主题交换机匹配规则 一、转发规则实现 1.1、需求分析 这里主要实现 routingKey 和 bindingKey 参数的校验&#xff0c;以及 Topic…

Python(.pyc)反编译:pycdc工具安装与使用

本文将介绍如何将python的.pyc文件反编译成源码&#xff0c;以便我们对源码的学习与改进。pycdc工具安装 下载地址&#xff1a; 1、Github地址&#xff1a;https://github.com/zrax/pycdc &#xff0c;下载后需要使用CMake进行编译。 2、已下载好及编译好的地址&#xff1a;ht…

ISIS路由协议

骨干区域与非骨干区域 凡是由级别2组建起来的邻居形成骨干区域&#xff1b;级别1就在非骨干区域&#xff0c;骨干区域有且只有一个&#xff0c;并且需要连续&#xff0c;ISIS在IP环境下目前不支持虚链路。 路由器级别 L1路由器只能建立L1的邻居&#xff1b;L2路由器只能建立L…

1.2 Kali Linux的网络配置

前言 最新文章请见此处&#xff0c;持续更新&#xff0c;敬请订阅&#xff01;https://blog.csdn.net/algorithmyyds/category_12418682.html 网络在如今的社会已是十分重要的媒介&#xff0c;如果没有网络&#xff0c;很多事情将难以办成。渗透测试也是一样——毕竟在攻击机…

Node opensslErrorStack 错误解决方法记录

从Git仓库中下载了一个老项目&#xff0c;使用npm install 安装后没有问题&#xff0c;当我使用npm run dev 的时候遇到了 OpenSSL 相关错误&#xff0c;例如 opensslErrorStack: [error:03000086:digital envelope routines::initialization error] 网上找了一下相关信息&am…

c# 数组反转

一个数组是{1&#xff0c;2&#xff0c;3&#xff0c;4&#xff0c;5&#xff0c;6}&#xff0c;把它变成{6&#xff0c;5&#xff0c;4&#xff0c;3&#xff0c;2&#xff0c;1} 1.创建一个和原数组长度类型一样的数组来接收反转的数据 private static void Main(string[] a…

学习设计模式之享元模式,但是宝可梦

前言 作者在准备秋招中&#xff0c;学习设计模式&#xff0c;做点小笔记&#xff0c;用宝可梦为场景举例&#xff0c;有错误欢迎指出。 享元模式 1 介绍 享元模式很好理解&#xff0c;它主要是为了减少创建对象的数量&#xff0c;属于结构型设计模式 目的&#xff1a;减少…

Python数据容器(列表list、元组tuple、字符串str、字典dict、集合set)详解

一、数据容器概念 相关介绍&#xff1a; 一种可以容纳多份数据的数据类型&#xff0c;容纳的每一份数据称之为一个元素。每一个元素&#xff0c;可以是任意类型的数据分为五类&#xff1a;列表[list]、元组(tuple)、字符串(str)、集合{set}、字典{dict} 相应区别&#xff1a…

Dubbo之PojoUtils源码分析

功能概述 PojoUtils是一个工具类&#xff0c;能够进行深度遍历&#xff0c;将简单类型与复杂类型的对象进行转换&#xff0c;在泛化调用时用到&#xff08;在泛化调用中&#xff0c;主要将Pojo对象与Map对象进行相互转换&#xff09; 功能分析 核心类PojoUtils分析 主要成员…

Jacoco XML 解析

1 XML解析器对比 1. DOM解析器&#xff1a; ○ 优点&#xff1a;易于使用&#xff0c;提供完整的文档树&#xff0c;可以方便地修改和遍历XML文档。 ○ 缺点&#xff1a;对大型文档消耗内存较多&#xff0c;加载整个文档可能会变慢。 ○ 适用场景&#xff1a;适合小型XML文档…

函数式编程-Stream流学习第二节-中间操作

1 Stream流概述 java8使用的是函数式编程模式,如同它的名字一样&#xff0c;它可以用来对集合或者数组进行链状流式操作&#xff0c;让我们更方便的对集合或者数组进行操作。 2 案例准备工作 我们首先创建2个类一个作家类&#xff0c;一个图书类 package com.stream.model;…

03.sqlite3学习——数据类型

目录 sqlite3学习——数据类型 SQL语句的功能 SQL语法 SQL命令 SQL数据类型 数字类型 整型 浮点型 定点型decimal 浮点型 VS decimal 日期类型 字符串类型 CHAR和VARCHAR BLOB和TEXT SQLite 数据类型 SQLite 存储类 SQLite 亲和类型(Affinity)及类型名称 Boo…