CD22.【C++ Dev】类和对象(13) 流提取运算符的重载和const成员

目录

1.流提取运算符>>的重载

知识回顾

重载方法

operator<<格式

operator>>格式

使用cin对日期类对象写入数据

如果想指定格式输入

方法1:getchar()

方法2:使用临时变量接收字符

完善operator>>代码(修bug)

2.类中的权限问题(const成员)

问题

分析

建议

解释:成员函数后面加const以后普通对象和const对象都可以调用

3.const练习


承接CD21.【C++ Dev】类和对象(12) 流插入运算符的重载文章

1.流提取运算符>>的重载

知识回顾

流提取运算符的基础知识参见CC2.【C++ Cont】初认识cout,cin和endl文章

重载方法

和CD21.【C++ Dev】类和对象(12) 流插入运算符的重载文章的operator<<重载格式一样

operator<<格式

ostream& operator<<(ostream& out, const Date& d)

operator>>格式

(来自https://legacy.cplusplus.com/reference/istream/istream/operator%3E%3E/)

查资料可知,返回值应该为istream&,第一个参数的也为istream&

istream& operator>>(istream& in, const Date& d)
{//......return in;
}

 注意:两个参数都不能使用const修饰

1.cin是一个全局对象,输入实际上是通过的cin这个对象,输入的东西需要cin去接受,如果加了const,cin就无法修改

2.由于需要对d的成员变量写入数据,不能加const

在类里面写operator>>友元函数声明,便于访问私有成员变量:

class Date
{friend ostream& operator<<(ostream& out, const Date& d);friend istream& operator>>(istream& in, Date& d);
public://......
private:int _year;int _month;int _day;
};

使用cin对日期类对象写入数据

istream& operator>>(istream& in, Date& d)
{in >> d._year >> d._month >> d._day;return in;
}

测试代码:

#include "Date.h"
int main()
{Date d1(0, 0, 0);cin >> d1;cout << d1;return 0;
}

运行结果:

如果想指定格式输入

方法1:getchar()

例如输入2025/3/31.可以这样修改代码

istream& operator>>(istream& in, Date& d)
{in >> d._year;getchar();in >> d._month;getchar();in>> d._day;return in;
}

运行结果:

方法2:使用临时变量接收字符

该临时变量仅接收字符,并无实际作用,所以起名为unused

istream& operator>>(istream& in, Date& d)
{char unused;in >> d._year >> unused >> d._month >> unused >> d._day;return in;
}

运行结果:

完善operator>>代码(修bug)

代码要有鲁棒性,因此需要对非法日期做处理

1.月必须介于1~12之间

2.天数必须合法

istream& operator>>(istream& in, Date& d)
{in >> d._year >> d._month >> d._day;if (d._month < 1 || d._month>12){cout << "非法日期" << endl;exit(EXIT_FAILURE);//错误退出}if (d._day <= 0 || d._day > GetMonthDay(d._year,d._day)){cout << "非法日期" << endl;exit(EXIT_FAILURE);//错误退出}return in;
}

(也可以将exit(EXIT_FAILURE)改成assert(false),因为里面为false,为无条件断言

其他写法:将判断条件写入assert中:

istream& operator>>(istream& in, Date& d)
{in >> d._year >> d._month >> d._day;assert(!(d._month < 1 || d._month>12));assert(!(d._day <= 0 || d._day > GetMonthDay(d._year, d._month)));return in;
}

这样断言的好处:能具体告诉日期的哪一个部分是非法的,例如:

1.月份是非法的

2.天数是非法的

2025年不是闰年,2月最多28天

运行结果:

发现退出代码不为0,这和头文件中EXIT_FAILURE定义的值有关

(VS2022的stdlib.h中有定义)

2.类中的权限问题(const成员)

使用const绕不开权限的放大缩小平移的问题,看下面的例子:

Date中的Print函数:

void Date::Print()
{cout << _year << "/" << _month << "/" << _day << endl;
}

测试代码:

#include "Date.h"
int main()
{const Date d1(2025, 3, 31);d1.Print();return 0;
}

报错:

分析:

Print()中隐藏的参数是this,虽然this指针的类型为const Date*,但是 const Date*中const只表示this指针本身不能修改,并没有表示this指向对象的成员变量不能修改

 实参this表示this指向的成员变量不可以修改(const Date d1(2025, 3, 31);),但Print()接收的this表示this指向的成员变量可以修改(void Date::Print()),导致权限的放大

解决方法:在Print函数后面加上const即可,const修饰*this(注意星号),这样就为权限的平移

void Date::Print() const//const修饰*this,this的类型为const Date* const
{cout << _year << "/" << _month << "/" << _day << endl;
}

(注加上的const不能写在Print()的括号里面,隐式参数this类型不能在括号里面修改,这是语法规定)

运行结果:

问题

下面是权限的平移放大还是缩小?是否正常运行?

void Date::Print() const
{cout << _year << "/" << _month << "/" << _day << endl;
}//......#include "Date.h"
int main()
{Date d1(2025, 3, 31);d1.Print();return 0;
}

分析

Date d1(2025, 3, 31);表示this指向的对象可以修改,void Date::Print() const表示this指向的对象不可以修改,从可以修改到不可以修改为权限的缩小,正常运行

建议

★如果对象的成员变量不改变(注意前提),最好在成员函数的后面加上const,成员函数后面加const以后普通对象和const对象都可以调用

例如日期+天数,日期类对象不改变,则在operator+函数后加上const

提醒:非成员函数上不允许修饰符const

(operator<<不是成员函数,没有使用Date::)

但也不能不看实际情况就加const

例如operator-复用了operator-=的代码,加了const就不能对*this修改

解释:成员函数后面加const以后普通对象和const对象都可以调用

测试代码:

#include "Date.h"
int main()
{const Date d1(2025, 3, 31);Date d2(2025, 4, 1);d1 < d2;d2 < d1;return 0;
}

分别对加了const和没有加const的operator<测试

先分析没有加const的:

bool Date::operator< (const Date& d2)
{if (_year < d2._year)return true;else if (_year == d2._year && _month < d2._month)return true;else if (_year == d2._year && _month == d2._month && _day < d2._day)return true;return false;
}

读测试代码可知:

d1<d2的执行会有问题,由d1的定义可知:d1的成员对象不能修改,而bool Date::operator< (const Date& d2)第一个参数为this,与d1的地址对应,导致权限的放大,会报错

d2<d1执行没有问题,是权限的缩小,没有问题

再分析加了const的:

d1<d2:权限的平移,没有问题

d2<d1:权限的缩小,没有问题

3.const练习

1. const对象可以调用非const成员函数吗?
2. 非const对象可以调用const成员函数吗?
3. const成员函数内可以调用其它的非const成员函数吗?
4. 非const成员函数内可以调用其它的const成员函数吗?

答案见下篇

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

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

相关文章

Spring 核心技术解析【纯干货版】- XIX:Spring 日志模块 Spring-Jcl 模块精讲

在现代 Java 开发中&#xff0c;日志是调试、监控和维护应用程序的重要工具。Spring 作为企业级框架&#xff0c;提供了 Spring-Jcl 作为日志抽象层&#xff0c;使开发者可以灵活切换不同的日志实现&#xff0c;而无需修改业务代码。本篇文章将深入解析 Spring-Jcl 模块&#x…

Hadoop集群---运维管理和技巧

一. daemon 守护进程管理 1. NameNode守护进程管理 hadoop-daemon.sh start namenode 2. DataNode守护进程管理 hadoop-daemon.sh start datanode 3. ResourceManager守护进程管理 yarn-daemon.sh start resourcemanager 4. NodeManager守护进程管理 yarn-daemon.sh st…

ngx_log_init

定义在 src\core\ngx_log.c ngx_log_t * ngx_log_init(u_char *prefix, u_char *error_log) {u_char *p, *name;size_t nlen, plen;ngx_log.file &ngx_log_file;ngx_log.log_level NGX_LOG_NOTICE;if (error_log NULL) {error_log (u_char *) NGX_ERROR_LOG_PATH;}…

网络华为HCIA+HCIP 策略路由,双点双向

目录 路由策略&#xff0c;策略路由 策略路由优势 策略路由分类 接口策略路由 双点双向 双点双向路由引入特点: 联系 路由回灌和环路问题 路由策略&#xff0c;策略路由 路由策略:是对路由条目进行控制&#xff0c;通过控制路由条目影响报文的转发路径&#xff0c;即路…

水下成像机理分析

一般情况下, 水下环境泛指浸入到人工水体 (如水库、人工湖等)或自然水体(如海洋、河流、湖 泊、含水层等)中的区域。在水下环境中所拍摄 的图像由于普遍受到光照、波长、水中悬浮颗粒物 等因素的影响&#xff0c;导致生成的水下图像出现模糊、退 化、偏色等现象&#xff0c;图像…

MySQL的数据目录以及日志

1.MySQL数据目录 MySQL服务器的管理信息、业务数据、⽇志⽂件、磁盘缓冲⽂件默认存储在数据⽬录下.数据目录保存了我们用户的信息,以及我们创建的数据库和表的数据.维护了日志文件等.mysqld主要操作的就是我们的数据目录. 如何查看数据目录: ll /var/lib/mysql#ll 是查看指令 …

论文阅读:Dual Anchor Graph Fuzzy Clustering for Multiview Data

论文地址:Dual Anchor Graph Fuzzy Clustering for Multiview Data | IEEE Journals & Magazine | IEEE Xplore 代码地址&#xff1a;https://github.com/BBKing49/DAG_FC 摘要 多视角锚图聚类近年来成为一个重要的研究领域&#xff0c;催生了多个高效的方法。然而&#…

32f4,串口1,usart.c.h2025

usart.c #include "sys.h" #include "usart.h" #include "led.h" // #include "stdlib.h" #include "stdarg.h" #include "stdio.h" //加入以下代码,支持printf函数,而不需要选择use MicroLIB #if 1#pragma…

C语言:一组位操作宏

解析协议时&#xff0c;取得位域的值是一种常见操作&#xff0c;这些宏可以辅助我们工作。 /* ** 将x的第n位置1 ** ** x 0x00000000 ** BIT_SET(x, 7) 0x00000080 */ #define BIT_SET(x, n) ((x) | (1 << (n)))/* ** 将x的第n位置为0 ** ** x 0x00000080 ** …

记一个使用BigDecimal所有类型变为整数的问题

场景 通过 Excel 导入数据&#xff0c;数据中包含金额。数据库类型 decimal(18, 6) 问题 Excel 导入后所有的金额列都被四舍五入。经过测试&#xff0c;只有数据有整数时所有数据才会被四舍五入&#xff0c;全部为浮点类型没有问题。 解决 强制设置小数位数 // RoundingM…

nodejs、socket.io、express + 实时线上聊天系统(自用笔记)

留个链接给自己参考用&#xff1a; socket.io官方文档&#xff1a;介绍 | Socket.IO nodejs基础语法&#xff1a;大前端技能讲解&#xff1a;NodeJS、Npm、Es6、Webpack_nodejs webpack-CSDN博客 socket.io教学&#xff1a;半小时学会socket.io【中英字幕】Learn Socket.Io …

配置网络编辑器

网络断开的原因 1.由于网络未连接的情况 解决方法 方法1&#xff1a;检查网卡配置 cd /etc/syscongfig/network_scripts vi ifcfg_ens31 方法2&#xff1a;打开虚拟机编辑--- 虚拟网络编辑器 查看ip地址是否在可用的网段范围内 修改后重启网络 systemctl restart netwo…

vscode代码片段的设置与使用

在 Visual Studio Code (VS Code) 中&#xff0c;可以通过自定义**代码片段&#xff08;Snippets&#xff09;**快速插入常用代码模板。以下是详细设置步骤&#xff1a; 步骤 1&#xff1a;打开代码片段设置 按下快捷键 Ctrl Shift P&#xff08;Windows/Linux&#xff09;或…

基于S函数的simulink仿真

基于S函数的simulink仿真 S函数可以用计算机语言来描述动态系统。在控制系统设计中&#xff0c;S函数可以用来描述控制算法、自适应算法和模型动力学方程。 S函数中使用文本方式输入公式和方程&#xff0c;适合复杂动态系统的数学描述&#xff0c;并且在仿真过程中可以对仿真…

做题记录:和为K的子数组

来自leetcode 560 前言 自己只会暴力&#xff0c;这里就是记录一下前缀和哈希表的做法&#xff0c;来自灵神的前缀和哈希表&#xff1a;从两次遍历到一次遍历&#xff0c;附变形题 正文 首先&#xff0c;这道题无法使用滑动窗口&#xff0c;因为滑动窗口需要满足单调性&am…

浅浅尝试Numpy的函数:

1.numpy.empty: numpy.empty方法用来创建一个指定形状&#xff08;shape&#xff09;&#xff0c;数据类型&#xff08;dtype&#xff09;且未被初始化的数组&#xff1a; numpy.empty(shape,dtype float,order C) 参数说明&#xff1a; shape:数组形状。 dtype:数据类型&am…

IM基本设计思路与有序ID的重要性

文章目录 概要问题解析思考问题数据基础读取写入总结 概要 说起IM程序我们都不陌生&#xff0c;本篇文章我们就为如何实现一个IM做一个简单的整体方案设计以及基本的数据结构 问题解析 我们先不上一大堆牛逼哄哄的中间件。 我们先从实现角度&#xff0c;来讲讲设计思路。 从…

数据结构学习

链表 单链表 头插 将x插到下标是k的点后面 将下标是k的点后面的点删掉 代码 // head 表示头结点的下标 // e[i] 表示节点i的值 // ne[i] 表示节点i的next指针是多少 // idx 存储当前已经用到了哪个点// 初始化 void init() {head -1;idx 0; }// 将x插到头结点 void add_to_…

0.DJI-PSDK开发准备及资料说明(基于DJI经纬M300RTK和M350RTK无人机上使用)

0.DJI-PSDK开发准备及资料说明&#xff08;基于DJI经纬M300RTK和M350RTK无人机上使用&#xff09; 【资料名称】 DJI经纬M300RTK和M350RTK无人机二次开发资料包。资料包在最下方的百度网盘 一、引言 在进行大疆无人机负载开发的过程中&#xff0c;我整理出一系列有价值的资…

Linux内核TCP/IP协议栈中的设计模式:从面向对象到系统级软件的跨界实践

引言 设计模式(Design Patterns)自GoF(Gang of Four)在1994年提出以来,已成为软件工程领域的核心概念。尽管其经典定义基于面向对象编程(OOP),但设计模式的本质是解决复杂问题的经验总结,而非局限于特定编程范式。本文以Linux内核的TCP/IP协议栈为例,探讨设计模式在…