定义Date类,创建date类
Yyds干货库存
写之前,今天我们先写一个Date类作为c初始类的结束,这里涉及到的知识,包括很多运算符的重载,我们都已经分享过了,所以不要着急,这里总结一下。我这里用的是Linux环境,主要是锻炼自己的能力。
我们想完成什么样的约会课程?您可以搜索时间计算器,我们将完成他们的功能,如添加或减去300天或查看两个日期之间的天数。这是我们的任务。
准备在这里,我们用三个文件来写,分别是date.h,date.cpp,test.cpp,先做好初始工作,先把框架摆出来,下面的函数一个一个补上。
日期. h
# include iostream # include assert . h使用STD:cout;使用STD:endl;class Date { public:Date(int year=1900,int month=1,int day=1);//析构函数~ Date();//复制建造日期(const Date d);private:int _ year;int _ monthint _ day};
Date.cpp
# include Date . h Date:Date(int year,int month,int day){ } ~ Date(){ } Date(const Date d){ }
测试. cpp
# include date . h int main(){ return 0;}
构造函数我们先来写date类的构造函数。本来这不是问题,但是我们知道一个月的天数是有限制的,同年也有闰年。这个考虑起来有点难,但是必须符合我们的客观规律。我们先理顺一下思路。
首先,我们给对象年和月,它们都必须是大于0的整数。这是毋庸置疑的。第二,我们要判断一年是偶数年还是闰年。第三,我们要判断给定月份对应的天数是否合理。
我们使用不同的方法来满足各自的需求。
很容易判断是偶数年还是闰年。记得在类中声明这个方法。
bool Date:isLeap(int year)
{
断言(第0年);
return(年份% 4==0年0!=0)
年% 400==0;
}判断天数是否合理我们都知道每个月都有一个固定的天数,而这个月肯定是少于13的,
int Date:is legimate(int year,int month)
{
static int monthDay[13]={0,31,28,31,30,31,30,31,30,31,30,31,30,31 };
断言(第0个月第13个月);
//判断闰年,月份是二月
if(isLeap(year) month==2)
{
返回29;
}
返回month day[month];
}我来解释一下为什么我们在定义数组的时候要用static?我们知道,这是一个函数,也就是说函数的堆栈框架最后会被销毁,但是我们可能会多次调用这个函数。为了避免多次打开破坏数组的空间,这里我们可以直接用静电装饰。
编写构造函数。这里已经写了构造函数,其他的就不用说了。
Date:Date(整数年=1900,整数月=1,整数日=1)
{
if(year 0 month 0 month 13 day=is legimate(year,month))
{
_year=年份;
_month=月;
_day=天;
}
其他
{
//这里应该抛出一个异常
//现在我不太会用assert代替。
断言(空);
}
}析构函数复制构造说实话,这两个函数我们都不用写。主要原因是我们没有使用动态空间。都是基本内容,编译器已经生成够了。在这里,大家可以看看。
因为这两个函数都不大,所以这里声明为内联函数,在类中实现。
//析构函数
内嵌~日期()
{
_ year=0;
_ month=0;
_ day=0;
}
//复制构造
内嵌日期(常数日期d)
{
_ year=d. _ year
_ month=d. _ month
_ day=d. _ day
}运算符重载。从某种意义上说,操作符过载是我们今天最大的问题。我们需要重载那些对我们来说合理的操作符,而不是重载所有的操作符。比如在日期上加一个日期是没有意义的,这里就不重载了。
逻辑运算符重载,一个基本的逻辑运算符,是有意义的。在这里,我们一一过载,验证。
过载==这个很好写。如果日期都相等,则两个日期必须相等。
布尔日期:运算符==(常数日期d)常数
{
return _ year==d. _ year
_ month==d. _ month
_ day==d. _ day
}
如果日期过载的年数越大,它就一定越大。如果相等,比较月份。如果月份仍然相等,比较日子。这是这个的原理。
布尔日期:运算符(常数日期d)常数
{
返回(_year d._year)
(_ year==d . year _ month d . month)
(_ year==d . year _ month==d . month _ day d . day);
}
过载=只要我们把上面两个做完,后面就可以直接调用了,避免反复做轮子。
布尔日期:运算符=(常数日期d)常数
{
return * this d * this==d
}
从现在开始,我不会演示结果。他们都和以前一样。
我们知道小于的反义词是大于或等于。
布尔日期:运算符(常数日期d)常数
{
回归!(* this=d);
重载的反义词=小于或等于大于,我们已经实现了。
布尔日期:运算符=(常数日期d)常数
{
回归!(*本d);
}超载!=这个更简单。不就是等于等于的对立面吗?
布尔日期:运算符!=(常数日期d)常数
{
回归!(* this==d);
}算术运算符的重载相当简单。这里,我们需要用加法、等式、减法、前后运算重载算术运算符.哪个难,尤其是加减法。
基本上重载=等于的时候对我们来说没有问题,但是有一点需要我们注意。C语言和C语言都支持串联,也就是a=b=c,也就是说重载等于的时候,我们必须有一个返回值。
日期日期:运算符=(常数日期d)
{
//避免重复
如果(这个!=d)
{
_ year=d. _ year
_ month=d. _ month
_ day=d. _ day
}
返回* this
}过载说实话,加号比较简单。首先,我们要判断给定的天数。如果它小于零,我们称之为重载减号。后面我会实现减法。这里,先考虑一下。
那么如何才能改善这种逻辑呢?第一步是直接把给定的天数加到_day上。如果它没有超过当月的最大天数,我们可以简单地返回到这个日期。否则,我们将减去当前月份的最大天数,并在当前月份中加1。注意,如果当前月份是12月,我们就直接把月份设为1,年份加1。这里要注意一点,不会修改原来的日期。
我们可以分为三种情况,我列举的每一种情况本质上都是一个循环。
2022-2-1 12 _ day=13二月最大值,返回四月最大值,2022-2-132022-4-30 _ day=37,十月_ day-=1=5。我们发现_ day=7月和5月的最大值,结束循环2022-12-31 2 _ day=33。十二月的最大值是_day-=31,月份是12。直接设置为1,_ year加1。继续循环,判断_day=2是否满足循环条件Date:operator(const int day)const。
{
//首先确定day是否小于零
如果(第0天)
{
返回(* this)-(-day);
}
//第一步,找第三方。不要修改原件
日期ret(* this);//这是一个复制构造。
ret。_day=天;
而(ret。_day ret.isLegitimate(ret。_年,退休。_月))
{
ret。_day -=ret.isLegitimate(ret。_年,退休。_月);
如果(ret。_month==12)
{
ret。_ month=1;
ret。_ year=1;
}
其他
{
ret。_ month=1;
}
}
返回ret
}过载=我们可以直接重用and=了。这里没什么好分享的。
Date Date:operator=(常数int day)
{
//确定它是否小于0
如果(第0天)
{
返回(* this)=(* this)-(-day);
}
返回(*this)=(*this)天;
}重载——如果我们要重载这里的加号,需要分两种情况。
很荣幸成为天数和日期。c支持重载,我们就按照步骤来。
就是天数,就是计算一个日期减去多少天得到另一个日期。也比较简单。我们要考虑一些情况,这里小于零的情况就不解释了。主要看我们的思维。
首先,我们从_day中减去_day来确定它是否小于0。如果是,我们将把它从上个月的日期加到_ day,直到它大于0。这里需要注意的是,如果我们的月份恰好是12,那么最后一个月就是1月,那一年就减1。
日期日期:运算符-(常数int day)常数
{
//一天的大小
如果(第0天)
{
返回(* this)(-天);
}
日期ret(* this);
ret。_ day-=day;
//开始判断ret。_日
而(ret。_day=0)
{
//查找上个月的
如果(ret。_month==1)
{
ret。_ month=12
ret。_ year-=1;
}
其他
{
ret。_ month-=1;
}
int days=ret.isLegitimate(ret。_年,退休。_月);
ret。_day=天数;
}
返回ret
}参数是日期,比较简单。我们计算两个日期之间的天数。我们可以重复使用以前的方法。
先说想法。我们认为,如果一次添加一个较小的日期,直到它与较大的日期完全相同,我们可以通过计算添加的次数来完成该运算符的重载。那么,我们如何得到较小的日期,比较它,然后交换它呢?我们使用一个标志位。我们假设日期A小于日期B,标志位为flag=1。如果没有,我们编程标记。
int Date: operator-(常量日期d)
{
//给出一个要计数的数字
int count=0;
int flag=1;
//不能修改原来的。这里使用了第三方
日期ret(* this);
if(ret d)
{
flag=-1;
}
而(ret!=d)
{
ret=flag
数数;
}
返回标志*计数;
}过载-=这个我们可以复用负号,就不解释了。
Date Date:operator-=(const int day)
{
如果(第0天)
{
返回(* this)=(* this)(-天);
}
返回(*this)=(*this) -天;
}重载我们就不解释前后的区别了。上一篇博客里分享过,直接开始吧。
前置不需要参数。
日期日期:运算符()
{
* this=1;
返回* this
}后置需要带一个int类型的参数。
日期日期:运算符(整数天)
{
日期ret(* this);
* this=1;
返回ret
}重载——既然我们都重载减法,那就直接重用吧。
没有前导参数
日期日期:操作员-()
{
* this-=1;
返回* this
}背带参数
日期日期:运算符-(整数天)
{
日期ret(* this);
* this-=1;
返回ret
}重载流提取和流插入的原理我们已经分享过了,这里就不赘述了。记得用朋友。
std:istream运算符(std:istream in,Date d)
{
年月日;
返回;
} std:ostream运算符(std:ostream out,Date d)
{
年月日-日-日;
退了出来;
}
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。