日期类的实现和取地址运算符重载

embedded/2024/10/15 3:46:54/

       前面将类学的差不多,接下来我们就来实现一下日期类。这个日期类包含运算符重载和前面学

的C++的语法知识。

      首先我们先建立一个日期类的头文件和源文件:

 一.日期类的头文件实现:

        首先我们要知道我们有闰年,还有每个月的天数也不一样,所有这里在写类时,就要注意哪

些年是闰年,哪些月有31天,哪些月是30天。

首先类中有三个私有的成员变量,年,月,日。

接下来就完成判断,哪些月的天数是30天和31天,再去判断哪些年是闰年,这样就导致2月是29

天。

所以这里我们就在类里去写一个函数,用来获取每个月的天数。

这里的Getmonthday函数,我们需要一个静态的数组来存贮每个月的天数,因为我们将这个数组

放到静态区去,这样频繁调用的话就不会再去创造空间,就直接可以用了。

为什么创建13个数组成员,因为数组开始为0,而没有0月,所以就用-1这个值来填这个位置,当

后面就是你是几月,就直接返回那个月的天数。

接下来就算判断是否为闰年还有2月了,如果是就返回29天。

这样整个的获取月的天数的函数就写好了。

写完这个就要将打印日期的声明和拷贝构造函数的声明也写到头文件中去,这样做到声明和定义

分离。

这样头文件的基本盘就写完了。

为什么其他函数的声明和定义是分开的呢,而Getmonthday不是呢,因为Getmonthday在后面会

使用的很频繁,这样不分开就算默认是内敛函数了

二.日期类运算符+的重载:

对于日期类的加,我们如果直接加的话就特别麻烦,你要知道这个月有多少天,每次都去进1,然

然后再去找当前这个月有多少天,所以就导致整个非常混乱并且不好实现。

                             

我们利用这个逻辑,比如我们要加的天数,我们直接加上去,然后我们再判断如果加完的天数,如

果大于本月的天数那么我们就进入一个循环,先用加完的天数减去本月的天数,然后月加一,如果

还是比加完月的月的天数大,就继续走上述循环,如果比其小了,就可以结束循环了。如果一开始

就没有超过那就更好了。

有了这样的思路我们就来实现一下代码,每个成员函数的第一个参数其实是隐藏的this指针。

C++类和对象(上)-CSDN博客

这里我们就可以回顾一下关于this指针的介绍。

看一下完整的代码:

如果月加到13了,就手动让其跳动到一月并且年也加一

这里也是一个构造函数,这里为什么要引进一个tmp的临时变量呢,就是因为这里是+,不会改变

原来的日期,这里要用传值返回不用引用返回,因为出了作用域临时对象的生命周期就结束了,所

以这里用传值返回。

这里就是错的,因为,这个加并不会改变他的值,所以要重新创建一个类来接收加完的值。

这两个写法是一样的

这样就正确了,我们看一下40天过后是不是11月21日

可以看出来是正确的。

三.日期类运算符+=的重载:

    上面写了+的运算符重载,其实现在就是改变原来的值,而上面的是自己不改变。

这里就是传引用返回,因为改变了其原本的值,所以直接用传引用返回,节省的传值返回的拷贝的

一个步骤

看一下运行结果:

既然加等写出来了,那么加的运算符重载就还有一个写法:

四.日期类运算符-的重载:

                           

这里用的思路是,原本的天数,减去往前推的天数,如果是小于0,就月往前推一个月,再用往前

推的那个月的天数去加那个小于0的天数,直到天数变为正即可,如果月数减到了0,那么就手动

减去一年,再手动将月调成12即可。

五.日期类运算符-=的重载:

    上面讲完减的运算符重载,其实-=跟+=的性质差不多,现在直接展示如何实现的:

    

六.日期类运算符<的重载:
 

这里就是如果年小就返回真,如果年相等就来比月,如果月小就返回真。如果月也相当,就返回天

的比较结果,如果天小就返回真,如果天大就返回假。其他情况并为一种就为假。

七.日期类运算符==的重载:

这里为什么先写==的运算符重载呢,因为再写后面的运算符这样就可以更简洁写出后面的运算符

重载。

八.日期类运算符重载<=的重载:

将上面两个<和<=的运算符重载写好后,可以直接赋用,使得<=的代码更加简洁高效。

因为前面的运算符已经写好了,所以直接赋用将两个参数传过去就行。

九.日期类运算符重载>的重载:

也就是取反一下,如果确实是小于等于那就为假,如果不是小于等于取反那就为真。

十.日期类运算符重载>=的重载:

总的来说这些大于等于的运算符先写两个出来然后其他的赋用一下就行了,非常的方便。

十一.日期类运算符重载++的重载:

重载++运算符时,有前置++和后置++,运算符重载函数名都是operator++,⽆法很好的区分。
C++规定,后置++重载时,增加⼀个int形参,跟前置++构成函数重载,⽅便区分。
相较于前置++和后置++ , 前置++是加了以后的值去进行操作,后置++是先操作后++,所以后
置++就多了很多拷贝,所以比较推荐使用前置++
在这里有圈出来的两种调用方式,其实这里的值他并没有接受,只是多一个参数与前置++构成一
下函数重载,这样才能更好的区分。
后置++的实现:
这里因为是后置++,所以返回的是加了之前的值,所以要弄一个临时变量来接受一下,最后再利
用传值返回,这里不用引用返回的原因就是这个临时变量出了作用域就不存在了,所以不用引用返
回。
前置++的实现:
这里就可以直接用传引用返回了,因为返回的就是加完以后的值,这样就减少拷贝,使得代码更
简洁。
这里来测试一下:
后置++接受完++的值后,打印出来的还是原来的值,再打印本身的话就已经加上去了。而前置
++打印出来的都是加完以后的值。

十二.日期类运算符重载--的重载:

前面的代码小问题:

这里如果+=一个负数的话就会出错,所以我们在这里不仅要考虑的是给的是正数还是负数。

因为传过来的是负数,所以是往前推算时间,所以直接就赋用-=然后将传的值给正即可。

这样就正确了。

然而-=也要修改:

十三.日期减日期的实现:

思路一:就是往前借日期去减

                 

这里问题就出来了,如果往前借12个月,有的月是30天有的月是31天,所以就很难计算。所以

这种办法就会很麻烦。

思路二:

就是做一个横向的减法:

这个方法比上面的更加简单,但是代码实现起来也有点复杂

思路三:

我们赋用前面的逻辑,我们做了比较大小,所以我们就先用假设法去做一个谁大谁小,然后去累加

再定义一个计数器,不断累加,直到两者的天数相等即可。这个不断累加确实计算麻烦,但是cpu

的计算能力很强,和上面的时间差不了多少。

思路三的实现:

因为我们不知道this接受的是大日期还是小日期,所以用一个flag去做一个标志,如果this是小日期

那么相差的天数就是负的。

也就是还有108天过年。

结果也就是正确的。

十四.检查日期的正确与否:

日期类的整个大逻辑也是实现好了,但是如果3月有30天,但我给日期的时候给错了,给了31天,

虽然电脑能计算出来但是是错误的,所以我们在构造日期类的时候要做一个检查,不能让错误的日

期继续算。

这里如果检查出来为假 就取反变为真去走if语句里面的逻辑,然后打印一下非法日期,这里不用给

参数,直接有this指针去检查。

这里直接检查出了非法日期。

十五.日期类重载输出流:

在前面都是封装好了一个类去运行,我们这里想要自己去输入一个日期,并不想要封装好的怎么办

这里我们就需要重载一下输入输出流。

之前我们说过C++的cout将常见的内置类型都写好了,所以不用像C语言那样用什么%d去输入输出

所以在这个日期类我们自己来重载一下输入输出流。

这里cout是ostream的类型,所以这里用out引用一下。out就是cout

这里就出错了,没办法匹配上

因为这里有两个参数,还有一个隐含的this指针,所以应该是d1传给this指针,而cout传给out的引

用,这里我们倒过来写一下,看看能否运行成功。

这样就成功运行了,但是这样写明显变得倒反天罡,变得很难看,所以不能这么写。

当年写成日期类里面的成员函数时,都会有默认的this指针,我们将运算符重载函数写成成员函数

的目的就是访问私有变量,那我们如果不想要这个this指针,我们就写成全局变量,让cout传给第

一个参数,日期类传给第二个参数。但是这样不能访问私有变量了,这里直接剧透,我们在类和对

象下会学习友元函数,我们将输出流的运算符重载函数定义成友元函数,这样我就可以访问里面的

私有的成员变量

但这里还有一个问题我们无法连续调用这个运算符重载:

因为这个cout是从左向右结合的先与d1结合再与d2结合,但这里输出流的函数重载无返回值,所以

匹配不上,所以这里我们要改一下返回的类型,我们也要返回一下out,这样就能连续匹配调用

了;

这里流对象是不支持拷贝的,所以必须使用引用返回

这样就可以连续调用了。

十六.日期类重载输入流:

这里就不是ostream了,这里就是istream了。

这里我们来测试一下:

这里优化一下,检查我们输入的日期是否是非法日期,如果非法就重新输入。

十七.取地址运算符的重载:

1 const成员函数:

权限可以缩小但是权限不能放大

接下来我们看个例子:

将const修饰的成员函数称之为const成员函数,const修饰成员函数放到成员函数参数列表的后
⾯。
const实际修饰该成员函数隐含的this指针,表明在该成员函数中不能对类的任何成员进⾏修改。
const 修饰Date类的Print成员函数,Print隐含的this指针由 Date* const this 变为 const
Date* const this, 所以就要在this指针前面加一个const,但是又因为this指针是隐藏的,在实参
形参的地方我们不能动。this指针前面是有个const的,是因为this指针是不能修改的。
解决方法就是在函数后面加一个const:
所以成员函数后面加加上const有极大的好处,普通对象和const对象都能调用,因为权限可以平移
和缩小,但是不能放大。但是不能一股脑的给所有成员函数加上const,因为有些函数就要修改成
员变量,不修改成员变量的建议加上const

2 取地址运算符重载:

取地址运算符重载分为 普通取地址运算符重载和const取地址运算符重载 ⼀般这两个函数编译器
⾃动⽣成的就可以够我们⽤了,不需要去显⽰实现 。除⾮⼀些很特殊的场景,⽐如我们不想让别⼈
取到当前类对象的地址,就可以⾃⼰实现⼀份,胡乱返回⼀个地址。
比如说这里使坏,不想让别人取到我日期类的地址:

http://www.ppmy.cn/embedded/127675.html

相关文章

腾讯云SDK点播播放数据

点播播放质量监控提供点播播放全链路的数据统计、质量监控及可视化分析服务。支持实时数据上报、数据聚合、多维筛选和精细化定向分析&#xff0c;可帮助企业实时掌控大盘运营状况、了解用户习惯和行为特征&#xff0c;有效指导运营决策、驱动业务增长。 注意事项 点播播放质…

装饰器模式(C++)

定义&#xff1a;装饰器模式&#xff08;Decorator Pattern&#xff09;是一种结构型设计模式&#xff0c;它允许你向一个现有的对象添加新的功能&#xff0c;同时又不改变其结构。这种类型的设计模式属于对象结构型模式&#xff0c;它是通过创建一个包装对象&#xff0c;也就是…

若依-医疗系统

项目介绍 湘雅三医院医疗系统是根据长沙市湘雅第三医院来开发的一款后台管理系统&#xff0c;是基于SpringBoot和Vue2开发的一款前端后端分离项目&#xff0c; 项目中包括&#xff1a;1&#xff1a;权限认证&#xff0c;动态菜单2&#xff1a;用户管理&#xff0c;部门管理&am…

【Linux】命令行下的增删查改之“查找“

根据路径和条件搜索指定文件(find) find 命令是 Linux 系统中一个极为重要和强大的工具&#xff0c;用于在目录树中递归查找文件和目录&#xff0c;能够根据多个条件进行筛选。 它适用于进行系统维护、文件管理和日志分析时文件的搜寻,既然其查找方式递归且从根目录开始,所以…

Spring MVC接收参数方式

1. 使用 RequestParam RequestParam 注解用于将请求中的参数绑定到控制器方法的参数上。 基本用法 GetMapping("/example") public String example(RequestParam("paramName") String param) {// 处理 paramreturn "result"; }可选参数 可以…

【笔记】408刷题笔记

文章目录 三对角三叉树求最小带权路径UDP报文首部和TCP报文首部IP报文首部TCP报文首部UDP报文首部 刷新和再生的区别地址译码 为了区分队空队满&#xff0c;可以使用三种处理方式 1&#xff09;牺牲一个单元 队头指针在队尾指针的下一位置作为队满的标志 队满条件&#xff1a;(…

FPGA驱动HDMI 初级篇

简介 本章节主要讲述如何通过FPGA驱动HDMI显示。 本章节框图如下: bd框图中使用了两个IP核,分别是Video Timing controller核AXI4-Stream to video out两个模块,下面先对两个模块做介绍。 Video Timing controller 配置如下: 这里由于没有使用ZYNQ PS端,…

[蓝桥杯 2017 省 B] 日期问题

小明正在整理一批历史文献。这些历史文献中出现了很多日期。小明知道这些日期都在 1960 年 1 月 1 日至 2059 年 12 月 31 日。令小明头疼的是&#xff0c;这些日期采用的格式非常不统一&#xff0c;有采用年/月/日的&#xff0c;有采用月/日/年的&#xff0c;还有采用日/月/年…