C++Date类的实现

目录

前言:

1.显示日期

2.构造函数与获取某年某月的日期的函数

3.日期比较

4.日期加减天数

5.日期减日期

6.前置后置++与--

7.完整代码

8.测试

总结:

感谢支持!


前言:

结合了前面的内容的学习,本篇来对之前的内容像运算符重载等进行应用,完成日期类的实现,具体功能大致包括对日期的加减比较,显示日期等。

1.显示日期

调用成员函数打印日期:

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

对流插入<<进行重载,完成对日期类的打印:

 定义文件中:

ostream& operator<<(ostream& out, const Date& d) 
{out << d._year << "/" << d._month << "/" << d._day << endl;return out;
}

声明文件中:

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

 为什么这里要用友元函数:

由于我们要使用的格式为例如,cout<<d1,如果放到成员函数中,由于对象调用成员函数会传对象的地址并在成员函数中用this指针接收,所以第一个参数只能是Date* this,也只能d1<<cout这样调用。

但是我们如果仅仅定义为一个普通函数就没法访问到类中的私有成员变量了,而且不能为了一个函数就让成员函数放为私有的,所以我们这里使用友元函数,既可以访问成员变量,也可以调整参数的顺序。

2.构造函数与获取某年某月的日期的函数

声明文件中:

	Date(int year = 1900, int month = 1, int day = 1);int GetMonthDay(int year, int month) const;

注意构造函数的缺省要在声明中给(如果声明和定义的缺省值不同,编译器无法确定,放在声明中也减少了其他源文件重复定义)。

定义文件中:

int Date::GetMonthDay(int year, int month) const
{assert(month > 0 && month < 13);int MonthArray[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))){return 29;//闰年}else{return MonthArray[month];}
}Date::Date(int year, int month, int day)
{if (year > 0 && (month > 0 && month < 13) && (day > 0 && day <= GetMonthDay(month, day))){_year = year;_month = month;_day = day;}else{cout << "初始化日期非法" << endl;}}

1.因为有闰年平年之分,还有不同的月的天数不同,所以我们要定义一个函数来获取具体到哪年哪月的具体的天数。

2.获取天数用一个数组来确定,方便下标与内容对应,多加一位;其次就是单独判断闰年的二月是29天,如果是,那就直接返回,如果不是,就返回对应下标的天数。

3.构造函数判断一下日期的合法性。 

3.日期比较

bool Date::operator==(const Date& d) const
{return _year == d._year&& _month == d._month&& _day == d._day;
}bool Date::operator<(const Date& d) const
{return (_year < d._year)|| ((_year == d._year) && (_month < d._month))|| ((_year == d._year) && (_month == d._month) && (_day < d._day));
}bool Date::operator<=(const Date& d) const
{return *this < d || *this == d;
}bool Date::operator>=(const Date& d) const
{return !(*this < d);
}
bool Date::operator>(const Date& d) const
{return !(*this <= d);
}bool Date::operator!=(const Date& d) const
{return !(*this == d);
}

可以先实现等于和小于的逻辑,其它的逻辑直接复用即可。 

4.日期加减天数

Date& Date::operator+=(int day) 
{if (day < 0){*this -= -day;//+=一个负的,就是让它走-=一个正的逻辑return *this;}_day += day;while (_day > GetMonthDay(_year,_month)){_day -= GetMonthDay(_year, _month);++_month;if (_month ==13){_year++;_month = 1;}}return *this;
}Date Date::operator+(int day) const
{Date tmp(*this);tmp += day;//复用,变得更简单//tmp._day += day;//while (tmp._day < GetMonthDay(tmp._year, tmp._month))//{//	tmp._day -= GetMonthDay(tmp._year, tmp._month);//	++tmp._month;//	if (tmp._month == 13)//	{//		tmp._year++;//		tmp._month = 1;//	}//}return tmp;
}Date& Date::operator-=(int day)
{Date tmp(*this);if (day < 0){*this += -day;//-=一个负的天数,就是走+=一个正的天数的逻辑return *this;}_day -= day;while (_day <= 0)//不够减,往上一个月借{--_month;if (_month == 0){--_year;_month = 12;}_day += GetMonthDay(_year, _month);}return *this;
}Date Date::operator-(int day) const
{Date tmp(*this);tmp -= day;return tmp;
}

 1.首先区分+=和-=与+和-的区别,+=和-=是会对原内容进行修改,也就是对对象进行修改,所以用引用返回,直接返回this指针,还能减少返回时产生的拷贝;而对于+和-来说,不能改变原有的对象,所以先调用编译器默认生成的拷贝构造来对对象进行一次拷贝(这里只有浅拷贝,不会出错),然后再对拷贝的对象复用+=或者-=的逻辑,再返回这个拷贝的对象即可,所以这里需要用一个返回值接收这个结果才能看出来。

2.要注意如果对天数进行操作时,天数为-怎么办。如果为负,在+=里面,就是要转换为-=了,所以写一句*this-=-day即可转换成去调用,因为day本身就是负的,所以就去调用*this-=day了;在-=则相反。

3.在+=中,我们要还要判断,当天数+的超过了这个月的天了,我们就要往下个月加了,如果加到下个月还多,那就再往下个月加,所以使用一个循环来实现,如果月加到了13,就要加到下一年去,并且让月再从一月开始,+也要考虑这个问题,但是我们复用了+=的逻辑,就不考虑了。

4.在-=中,我们要判断如果天数减的变为了负的,那就要往上一个月去借,然后让天数加上这个月的天数,如果借的还不够,继续借,所以使用循环来实现,注意如果月减到了0,就要往上一年借,并让月从12开始。-直接复用即可。

5.也可以先完成+-的逻辑,+=与-=再复用:
 

//如果先实现了+的逻辑,+=也可复用+的逻辑
//*this=*this+day;但是这个会先调operator+的函数,再调自动生成的operator赋值函数,所以建议使用第一种

这样就多了拷贝了,所以建议先实现+=与-=。

5.日期减日期

日期减日期可以有两种方法,可以先获取两个日期距离所在年的1月1日有多少天,再计算两个日期相差多少年,要考虑闰平年,然后再计算总共相差多少天即可。

或者使用下面的方法:

int Date::operator-(const Date& d) const
{Date max = *this;Date min = d;int flag = 1;if (*this < d){max = d;min = *this;flag = -1;}int n = 0;while (min != max){min++;n++;}return n * flag;
}

flag用来确定正负,n用来计算相差多少天。先假设左边的日期大,然后比较,如果右边大,交换顺序,并且右边大减出来肯定是负的,所以再让flag设为-1,然后让n计数,看相差多少天,然后返回天数*正反号即可。

6.前置后置++与--

Date& Date::operator++()
{*this += 1;return *this;
}
Date Date::operator++(int) 
{Date tmp(*this);*this += 1;return tmp;
}Date& Date::operator--()
{*this -= 1;return *this;
}Date Date::operator--(int)
{Date tmp(*this);*this -= 1;return tmp;
}

1.前置复用之前+=与-=的逻辑,直接返回这个修改后的对象;而后置是先拷贝,再对原对象进+=和-=的复用,再返回没有改变的拷贝的对象,这样接收返回值的时候,接收的就是没有改变的对象,但是原来的对象已经修改了,就起到了后置的效果。

2.编译器为了区分前置后置,在调用后置的时候,会传一个参数,可能是一个整形0,可能是其他的,所以重载的时候写一个int参数,这是编译器自动传的,不用我们自己传,自己传也行。

7.完整代码

定义文件:

#define _CRT_SECURE_NO_WARNINGS
#include "Date.h"int Date::GetMonthDay(int year, int month) const
{assert(month > 0 && month < 13);int MonthArray[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))){return 29;//闰年}else{return MonthArray[month];}
}Date::Date(int year, int month, int day)
{if (year > 0 && (month > 0 && month < 13) && (day > 0 && day <= GetMonthDay(month, day))){_year = year;_month = month;_day = day;}else{cout << "初始化日期非法" << endl;}}void Date::Print() const
{cout << _year << "/" << _month << "/" << _day << endl;
}bool Date::operator==(const Date& d) const
{return _year == d._year&& _month == d._month&& _day == d._day;
}bool Date::operator<(const Date& d) const
{return (_year < d._year)|| ((_year == d._year) && (_month < d._month))|| ((_year == d._year) && (_month == d._month) && (_day < d._day));
}bool Date::operator<=(const Date& d) const
{return *this < d || *this == d;
}bool Date::operator>=(const Date& d) const
{return !(*this < d);
}
bool Date::operator>(const Date& d) const
{return !(*this <= d);
}bool Date::operator!=(const Date& d) const
{return !(*this == d);
}Date& Date::operator+=(int day) 
{if (day < 0){*this -= -day;//+=一个负的,就是让它走-=一个正的逻辑return *this;}_day += day;while (_day > GetMonthDay(_year,_month)){_day -= GetMonthDay(_year, _month);++_month;if (_month ==13){_year++;_month = 1;}}return *this;
}Date Date::operator+(int day) const
{Date tmp(*this);tmp += day;//复用,变得更简单//tmp._day += day;//while (tmp._day < GetMonthDay(tmp._year, tmp._month))//{//	tmp._day -= GetMonthDay(tmp._year, tmp._month);//	++tmp._month;//	if (tmp._month == 13)//	{//		tmp._year++;//		tmp._month = 1;//	}//}return tmp;
}Date& Date::operator-=(int day)
{Date tmp(*this);if (day < 0){*this += -day;//-=一个负的天数,就是走+=一个正的天数的逻辑return *this;}_day -= day;while (_day <= 0)//不够减,往上一个月借{--_month;if (_month == 0){--_year;_month = 12;}_day += GetMonthDay(_year, _month);}return *this;
}Date Date::operator-(int day) const
{Date tmp(*this);tmp -= day;return tmp;
}int Date::operator-(const Date& d) const
{Date max = *this;Date min = d;int flag = 1;if (*this < d){max = d;min = *this;flag = -1;}int n = 0;while (min != max){min++;n++;}return n * flag;
}Date& Date::operator++()
{*this += 1;return *this;
}
Date Date::operator++(int) 
{Date tmp(*this);*this += 1;return tmp;
}Date& Date::operator--()
{*this -= 1;return *this;
}Date Date::operator--(int)
{Date tmp(*this);*this -= 1;return tmp;
}ostream& operator<<(ostream& out, const Date& d) 
{out << d._year << "/" << d._month << "/" << d._day << endl;return out;
}

声明文件:

#pragma once
#include <iostream>
#include <assert.h>using namespace std;class Date
{friend ostream& operator<<(ostream& out, const Date& d);
public:Date(int year = 1900, int month = 1, int day = 1);int GetMonthDay(int year, int month) const;void Print() const;bool operator==(const Date& d) const;bool operator<(const Date& d) const;bool operator<=(const Date& d) const;bool operator>=(const Date& d) const;bool operator>(const Date& d) const;bool operator!=(const Date& d) const;Date& operator+=(int day);Date operator+(int day) const; Date& operator-=(int day);Date operator-(int day) const;int operator-(const Date& d) const;Date& operator++();Date operator++(int);Date& operator--();Date operator--(int);private:int _year;int _month;int _day;
};

这样的成员函数没对成员变量进行修改的都加上了const修饰,方便不是const的对象和const的对象都能调用。

8.测试

#define _CRT_SECURE_NO_WARNINGS
#include "Date.h"void TestDate1()
{Date d1(2024, 4, 4);Date d2(2023, 4, 4);Date ret1=++d1;cout << d1;cout << ret1;Date ret2=d1++;cout << d1;cout << ret2;cout << endl;Date ret3=d1--;cout << d1;cout << ret3;Date ret4=--d1;cout << d1;cout << ret4;d1.Print();}void TestDate2()
{Date d1(2024, 4, 4);Date d2(2023, 4, 4);Date ret1=d1 + 100;cout << d1;cout << ret1;d1 += 100;cout << "d1此时为:" << d1;Date ret2=d2 - 100;cout << d2;cout << ret2;d2 -= 100;cout << "d2此时为:" << d2;cout << (d1 - d2) << endl;;cout << (d2 - d1) << endl;;}void TestDate3()
{Date d1(2024, 4, 4);Date d2(2023, 4, 4);cout << (d1 > d2) << endl;cout << (d1 < d2) << endl;cout << (d1 >= d2) << endl;cout << (d1 <= d2) << endl;cout << (d1 != d2) << endl;cout << (d1 == d2) << endl;}int main()
{TestDate3();return 0;
}

 

 

总结:

感谢支持!

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

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

相关文章

基于php医院预约挂号系统

摘 要 随着信息时代的来临&#xff0c;过去的管理方式缺点逐渐暴露&#xff0c;对过去的医院预约挂号管理方式的缺点进行分析&#xff0c;采取计算机方式构建医院预约挂号系统。本文通过阅读相关文献&#xff0c;研究国内外相关技术&#xff0c;开发并设计一款医院预约挂号系统…

语义分割交互式智能标注工具 | 澳鹏数据标注平台

随着人工智能应用的大规模落地&#xff0c;数据标注市场在高速增长的同时&#xff0c;也面临着标注成本的挑战。据IDC报告显示&#xff1a;数据标注在AI应用开发过程中所耗费的时间占到了25%&#xff0c;部分医学类应用一条数据的标注成本甚至高达20元。数据精度的高要求、强人…

【Flink技术原理构造及特性】

1、Flink简介 Flink是一个批处理和流处理结合的统一计算框架&#xff0c;其核心是一个提供了数据分发以及并行化计算的流数据处理引擎。它的最大亮点是流处理&#xff0c;是业界最顶级的开源流处理引擎。 Flink最适合的应用场景是低时延的数据处理&#xff08;Data Processin…

爬虫实战三、PyCharm搭建Scrapy开发调试环境

#一、环境准备 Python开发环境以及Scrapy框架安装&#xff0c;参考&#xff1a;爬虫实战一、Scrapy开发环境&#xff08;Win10Anaconda&#xff09;搭建 PyCharm安装和破解&#xff0c;参考&#xff1a;爬虫实战二、2019年PyCharm安装&#xff08;激活到2100年&#xff09; …

0基础如何进入IT行业?

0基础如何进入IT行业&#xff1f; 简介&#xff1a;对于没有任何相关背景知识的人来说&#xff0c;如何才能成功进入IT行业&#xff1f;是否有一些特定的方法或技巧可以帮助他们实现这一目标&#xff1f;我不知道&#xff0c;我的行业算不算是IT&#xff0c;或者最多是半个IT行…

重磅!openGauss6.0创新版本,带着新特性正式发布了!

&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&#x1f61c;&#x1f61c; 中国DBA联盟(ACD…

从“量子”到分子:探索计算的无限可能 | 综述荐读

在2023年年末&#xff0c;两篇划时代的研究报告在《科学》&#xff08;Science&#xff09;杂志上引发了广泛关注。这两篇论文分别来自两个研究小组&#xff0c;它们共同揭示了单氟化钙分子间相互作用的研究成果&#xff0c;成功地在这些分子间创造出了分子量子比特。这一成就不…

算法练习—day1

title: 算法练习—day1 date: 2024-04-03 21:49:55 tags: 算法 categories:LeetCode typora-root-url: 算法练习—day1 网址&#xff1a;https://red568.github.io 704. 二分查找 题目&#xff1a; 题目分析&#xff1a; 左右指针分别为[left,right]&#xff0c;每次都取中…

【机器学习】K-近邻算法(KNN)介绍、应用及文本分类实现

一、引言 1.1 K-近邻算法&#xff08;KNN&#xff09;的基本概念 K-近邻算法&#xff08;K-Nearest Neighbors&#xff0c;简称KNN&#xff09;是一种基于实例的学习算法&#xff0c;它利用训练数据集中与待分类样本最相似的K个样本的类别来判断待分类样本所属的类别。KNN算法…

ArcGIS Pro导出布局时去除在线地图水印

目录 一、背景 二、解决方法 一、背景 在ArcGIS Pro中经常会用到软件自带的在线地图&#xff0c;但是在导出布局时&#xff0c;图片右下方会自带地图的水印 二、解决方法 解决方法&#xff1a;添加动态文本--服务图层制作者名单&#xff0c;然后在布局中选定位置添加 在状…

dhcp中继代理

不同过路由器分配ip了&#xff0c;通过一台服务器来代替&#xff0c;路由器充当中继代理功能&#xff0c;如下图 服务器地址&#xff1a;172.10.1.1/24 配置流程&#xff1a; 1.使能dhcp功能 2.各个接口网关地址&#xff0c;配置dhcp中继功能 dhcp select relay &#xff0…

Qt | 发布程序(以 minGW 编译器为例)

1、注意:修改 pro 文件后,最好执行“构建”>“重新构建项目”,否则 pro 文件的更改将不会反应到程序上。 2、发布程序的目的:就是让编译后生成的可执行文件(如 exe 文件),能在其他计算机上运行。 一、编译后生成的各种文件简介 Qt Creator 构建项目后产生的文件及目录…

实时渲染 -- 材质(Materials)

一、自然界中的材质 首先了解下自然界中的材质 如上这幅图&#xff0c;不同的物体、场景、组合&#xff0c;会让我们看到不同的效果。 我们通常认为物体由其表面定义&#xff0c;表面是物体和其他物体或周围介质之间的边界面。但是物体内部的材质也会影响光照效果。我们目前只…

续二叉搜索树递归玩法

文章目录 一、插入递归二、寻找递归&#xff08;非常简单&#xff0c;走流程就行&#xff09;三、插入递归&#xff08;理解起来比较麻烦&#xff09; 先赞后看&#xff0c;养成习惯&#xff01;&#xff01;&#xff01;^ _ ^<3 ❤️ ❤️ ❤️ 码字不易&#xff0c;大家的…

ROS 2边学边练(11)-- colcon的使用

从此篇开始我们即将进入client library系列&#xff0c;主要包含包的创建、主题、服务、参数、消息等功能的自定义实现&#xff0c;开始真正进入ROS的大门咯。 前言 从ROS 1到ROS 2&#xff0c;对应的构建工具集由 catkin_make -> catkin_make_isolated ->catkin_tools …

Redis监控方案以及相关黄金指标提升稳定性和可靠性

Redis监控方案以及相关黄金指标提升稳定性和可靠性 1. 需要了解的词2. 「基准性能」相关指标2.1 Latency2.2 最大响应延迟2.3 平均响应延迟2.4 OPS(instantaneous_ops_per_sec)2.5 Hit Rate 3. 「内存」相关指标3.1 内存使用量(used_memory)3.2 内存碎片率(mem_fragmentation_r…

文件操作(详解)

该片博客有点长大家可以通过目录选择性阅读 这是个人主页 敲上瘾-CSDN博客 目录 1. 为什么使⽤⽂件&#xff1f; 2. 什么是⽂件&#xff1f; 2.1 程序⽂件 2.2 数据⽂件 2.3 ⽂件名 3. ⼆进制⽂件和⽂本⽂件&#xff1f; 4. ⽂件的打开和关闭 4.1 流和标准流 4.1.1 流…

【c/c++】深入探秘:C++内存管理的机制

&#x1f525;个人主页&#xff1a;Quitecoder &#x1f525;专栏&#xff1a;c笔记仓 朋友们大家好&#xff0c;本篇文章我们详细讲解c中的动态内存管理 目录 1.C/C内存分布2.C语言中动态内存管理方式&#xff1a;malloc/calloc/realloc/free3.c内存管理方式3.1new/delete对内…

【how2j练习题】JS部分阶段练习

练习题 1 <!-- 练习&#xff1a;自定义一个函数&#xff0c;对数组进行排序&#xff0c;要求排序后没有重复数据 --> <script>function p(s){document.write(s);document.write("<br>");}function uniquel(arr){ var hash[];for(var i 0;i<arr.…

Java源值1.5已过时,将在未来所有发行版中删除

1、背景 确认java项目没问题&#xff0c;但是启动的时候&#xff0c;却报错&#xff1a;java: -source 1.5 中不支持 diamond 运算符 2、解决 2.1 2.2 2.3 2.4 2.5