您的位置:首页 > 房产 > 家装 > CPP入门:日期类的构建

CPP入门:日期类的构建

2024/12/23 16:21:08 来源:https://blog.csdn.net/duanku111/article/details/139674348  浏览:    关键词:CPP入门:日期类的构建

目录

1.日期类的成员

2.日期类的成员函数

2.1构造和析构函数

2.2检查日期合法

 2.3日期的打印

 2.4操作符重载

2.4.1小于号

2.4.2等于号

2.4.3小于等于号

 2.4.4大于号

2.4.5大于等于号

2.4.6不等号

 2.4.7加等的实现

2.4.8加的实现

2.4.9减去一个天数的减等实现

2.4.10减去一个天数的减实现

2.4.11两个日期相减的实现

 2.4.12前后置++的实现

2.4.13前后置--的实现

 2.5流插入/流提取操作符


1.日期类的成员

实现一个日期类,内部的成员自然是年、月、日

class Date
{private:int _year;int _month;int _day;
};

在日期类中,我们应当是已知每个月份有多少天的,因此我们还需要在日期内中写一个成员函数来获得当月的天数。

	//获得天数int GetMonthDay(int year,int month){static int monthDayArray[13] = { -1, 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 monthDayArray[month];}}

此外,我们的日期类还应当能够实现对日期的打印、对日期类的相关计算、输入输出的重载等成员函数。

因此,我们完整的日期类应是如下:

#pragma once
#include <iostream>
using namespace std;
#include <assert.h>
class Date
{
public://流插入or输出friend ostream& operator<<(ostream& out, const Date& d);friend istream& operator>>(istream& in, Date& d);//构造Date(int year = 1900, int month = 1, int day = 1);//获取月份天数int GetMonthDay(int year, int month){assert(month > 0 && month < 13);static int monthDayArray[13] = { -1, 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 monthDayArray[month];}}//检查日期bool CheckDate();//打印日期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;
};
//输入流重载
ostream& operator<<(ostream& out, const Date& d);
//输出流重载
istream& operator>>(istream& in, Date& d);

2.日期类的成员函数

2.1构造和析构函数

由于日期类的成员都是内置类型,因此我们可以显式的写一个构造函数,但不用显式定义析构函数。

Date::Date(int year = 2024, int month = 7, int day = 2)
{_year = year;_month = month;_day = day;//检查日期合法性if (!CheckDate()){cout << "日期非法" << endl;}
}

由于我们的日期具有范围,因此我们需要在构造函数中检查日期是否合法。也正是因此,我们需要实现一个检查日期合法性的函数。

2.2检查日期合法

检查日期合法,首先要确保我们输入的数是正数,

//检查日期合法性
bool Date::CheckDate()
{if (_month < 1 || _month>12|| _day<1 || _day>GetMonthDay(_year, _month)||_year < 1){return false;}else{return true;}
}

 2.3日期的打印

void Date::Print() const 
{cout << _year <<'-' << _month <<'-'<<_day;
}

 2.4操作符重载

下面我们就需要重载一些对日期类计算有用的操作符

2.4.1小于号

由于我们不想要我们传入的参数会被修改,因此我们需要传递常量。(权限可以缩小)

另外,我们传引用有两个原因

  • 可以少一次构造形参的过程,可以提高性能。
  • d在函数运行结束后不会销毁,不会返回一个空引用。

因此我们的函数名为:

bool operator<(const Date& d) const

 判断一个日期是否小于另一个日期,我们需要分别判断年、月、日是否小于另一个日期。

在判断日的时候,我们可以直接使用原生的<操作符判断。

bool Date::operator<(const Date& d) const
{//年if (_year < d._year){return true;}else if (_year == d._year){   //月if (_month < d._month){return true;}else if (_month == d._month){//日return _day < d._day;//if (_day < d._day)//{//	return true;//}//else//{//	return false;//}}}
}

2.4.2等于号

直接判断年月日是否相等即可 

bool Date::operator==(const Date& d) const
{return _year == d.year&& _month == d._month&& _day == d._day;
}

2.4.3小于等于号

我们传入的第一个参数是this,因此我们解引用this即可得到第一个参数的值。 

bool Date::operator<=(const Date& d)const
{return *this < d || *this == d;
}

 2.4.4大于号

判断是否大于就是是否小于等于取反 

bool Date::operator>(const Date& d)const
{return !(*this <= d);
}

2.4.5大于等于号

 判断是否大于等于就是对判断是否小于取反

bool Date::operator>=(const Date& d)const
{return !(*this < d);
}

2.4.6不等号

判断是否不相等就是对判等取反

bool Date::operator!=(const Date& d)const
{return !(*this == d);
}

 2.4.7加等的实现

对于加等,是给定一个日期和一个天数,计算日期加上这个天数之后的日期。

这里我们采取的思路是先将原天数加上需要加的天数。

之后我们一直减去当月的天数,并让月份加1,如果月份为13,则年份加1,月份赋为1。一直到天数没有当月天数大为止。

Date& Date::operator+=(int day)
{//日期加_day+= day;//月份加while (_day > GetMonthDay(_year, _month)){if (_day > GetMonthDay(_year, _month)){_month++;_day - GetMonthDay(_year, _month);if (_month == 13){_month == 1;_year += 1;}}}return *this;
}

2.4.8加的实现

首先,我们实现两数相加,是不能改变我们的原数的。

因此,我们的第一个形参为const修饰的变量。

//加
//c=a+b;
Date Date::operator+(int day) const
{Date tmp = *this;tmp += day;return tmp;
}

这里我们采取的思路是创建一个临时变量来保存*this,然后返回tmp加等day的结果即可。

这里需要注意的是,由于这个函数运行结束之后,tmp会先被销毁掉,再进行返回,因此我们如果返回值为引用的话,则会出错。

2.4.9减去一个天数的减等实现

//减去一个天数
//减等
Date& Date::operator-=(int day)
{//减去一个负数if (day < 0){return *this += (-day);}//减去一个整数_day -= day;while (_day < 0){--month;if (_month == 0){_month = 12;_year--;}_day += GetMonthDay(_year, _month);}
}

与实现加等类似的是,这里我们也是类似的步骤,通过一个循环来不断的更新年月日。 

2.4.10减去一个天数的减实现

//减去一个天数
Date Date::operator-(int day)const
{Date tmp = *this;tmp -= day;return tmp;
}

这里和上面的加等相似。 

2.4.11两个日期相减的实现

首先,我们要判断出哪个日期大

之后,我们让小的日期不断加1,直到他们相同。

加了多少次1,两个日期就相隔多少天。 

//两个日期相减
Date Date::operator-(const Date& d)const
{//假设法判断谁大Date max = *this;Date min = d;if (min > max){max = d;min = *this;}//小的日期不断加一天,直到二者相等//设置一个计数器,计数器的值就是两个日期的差值int n = 0;while (min!+ max){min++;n++;}return n;
}

 2.4.12前后置++的实现

由于我们重载++操作符时都是这么写的:

Date::operator++()//前
Date::operator++(int)//后

这样便无法判断到底是调用前置++还是后置++了。

因此,我们规定调用后置++时,形参写一个int。

Date::operator++()//前
Date::operator++(int)//后

前置++非常容易实现,这里不再赘述。 

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

后置++是先使用后++的。因此我们创建一个临时变量来保存*this,并在返回tmp前对*this+1。

2.4.13前后置--的实现

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

 2.5流插入/流提取操作符

 观察下面两行代码,我们发现这两个操作符的第二个操作数才是this。

但是成员函数默认第一个操作数为this,这就产生了问题。

因此我们不能够将这两个函数声明为成员函数。

cout << n << endl;
cin << n ;

我们需要将这两个函数声明在类外,之后通过友元在类内访问即可。

//类内
friend ostream& operator<<(ostream& out, const Date& d);
friend istream& operator>>(istream& in, Date& d);
//定义
ostream& operator <<(ostream& out, const Date& d)
{cout << d._year << '-' << d._month << '-' << d._day;return out;
}
istream& operator>>(istream& in, Date& d)
{in >> d._year >> d._month >> d._day;if (!d.CheckDate()){cout << "日期非法" << endl;}return in;
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com