题目:定义日期类Date,包括年、月、日3个成员变量,在其中重载运算符“+”,“-”,“++”,“--”。(注意:需要考虑每个月不同天数及闰年问题)。
题目为《面向对象程序设计》(C++语言)--李爱华 程磊教材第七章课后题
好的,我们来分析一下题目,对类的声明进行功能定向,一个是对四个运算符的重载,这里我们遵循C++封装的特性,采用重载为成员函数的方法。
形如:
T operator @(参数表){
//函数体
}
其中T为返回类型,通常为类类型,operator为关键字,@就是我们要重载的运算符,参数表看我们的情况而定,分双目和单目。
结合我们的题目来看下具体要实现什么功能:
"+":给定一个日期,调用“+”运算符重载函数的话,则将日期增加到给定的参数天之后,例如:
Date operator+(int days);//实现将日期加到days天之后
同样,"-"则为将日期回到形参天数之前,"++"为日期加一天,"--"为日期减一天,我们来看他们的声明
Date operator++(int); //单目,日期加一
Date operator--(int); //单目,日期减一
Date operator+(int days); //双目,日期加days
Date operator-(int days); //双目,日期减days
看似很简单吧,但是我们在实现的时候还要考虑天数加减之后的问题,比如1月和2月的天数不一样,1月天数加到31才返回1,月数增加为2,2月的时候又要考虑是否闰年,再决定天数为28或者29时返回下月的1,这里我们先定义一个判断闰年的成员函数函数:
bool IsLeapYear(int year){ //判断是否为闰年
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
{
return true;
}
return false;
}
那么具体的天数循环我们放到运算符重载函数里面用循环来实现我们来看下完整的类的声明:
class Date{
private:
int month, day, year;
public:
Date(int y=2019, int m=11, int d=2):year(y),month(m),day(d);
Date(const Date &d);
~Date();
Date operator++(int); //日期加1,重载后置++
Date operator--(int); //日期减1,重载后置--
Date operator+(int days); //days天之后的日期
Date operator-(int days); //days天之前的日期
bool IsLeapYear(int year); //判断是否为闰年
void ShowDate(); //显示日期,格式如2000-10-01
首先定义operator++,我们只需要加几个循环,把月份分开处理即可,分为三类,即1,3,5,7,8,10,12月有31天,天数大于31即返回1,月数加1,其中12月份又有点特殊,如果12月天数大于31,则年份加1,月和天数都返回1;第二类是4,6,9,11月,天数大于30,月即可加1,天数返回1;最后是2月,需要先判断是否闰年,是,则29天返回循环,否,则28天进行月份循环。
Date Date::operator++(int){ //日期加1,重载后置++
switch (month)
{
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
if (day<31) {day += 1;}
else { day = 1; month += 1; }
break;
case 12:
if (day < 31) {
day += 1;
}
else {
day = 1;
month = 1;
year += 1;
}
break;
case 4:
case 6:
case 9:
case 11:
if (day < 30) {day += 1;}
else {
day = 1;
month += 1;
}
break;
case 2:
if (IsLeapYear(year)){
if (day < 29) day += 1;
else {
day = 1; month += 1;
}
}
else if (day<28){ day += 1; }
else
{
day = 1; month += 1;
}
break;
}
return *this;
}
Date Date::operator--(int){
switch (month)
{
case 1:
if (day == 1) { year -= 1; month = 12; day = 31; }
else day -= 1;
break;
case 3:
if (day != 1) day -= 1;
else {
if (IsLeapYear(year)) { day = 29; month = 2; }
else { day = 28; month = 2; }
}
case 2:
case 4:
case 6:
case 8:
case 9:
case 11:
if (day != 1) day -= 1;
else { day = 31; month -= 1;}
break;
case 5:
case 7:
case 10:
case 12:
if (day != 1) day -= 1;
else { day = 30; month -= 1; }
break;
}
return *this;
}
这两个定义之后,其他的就简单了,我们来看"+"和"-"。顺便把其他函数一起实现了:
Date Date::operator+(int days) //days天之后的日期
{
Date temp(*this);
for (int i = 0; i < days; i++)
{
temp++;
}
return temp;
}
Date Date::operator-(int days) //days天之前的日期
{
Date temp(*this);
for (int i = 0; i < days; i++)
{
temp--;
}
return temp;
}
bool Date::IsLeapYear(int year){ //判断是否为闰年
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
{
return true;
}
return false;
}
void Date::ShowDate(){ //显示日期,格式如2000-10-01
cout << year << "-" << month << "-" << day << endl;
}
因为本篇主要描述运算符重载和Date类的实现,并未涉及别的复杂的知识点,所以我们到这就直接给出主测试函数,来进行测试这个类的功能:
int main(){
Date d1, d2(1999, 5, 25), d3;
cout << "d1日期:";
d1.ShowDate();
cout << "d2日期:";
d2.ShowDate();
d3=d1++;
cout << "d1日期++:";
d3.ShowDate();
d3 = d2--;
cout << "d2日期--:";
d3.ShowDate();
d3 = d1 + 20;
cout << "d1日期+20天:";
d3.ShowDate();
d3 = d2 - 20;
cout << "d2日期-20天:";
d3.ShowDate();
return 0;
}
下面将程序整合,因为程序简短,就不分文件编程,直接给出.cpp文件运行代码:
//created by kong at 2019-11-02
#include
using namespace std;
class Date{
private:
int month, day, year;
public:
Date(int y=2019, int m=11, int d=2):year(y),month(m),day(d){ }
Date(const Date &d)
{year = d.year; month = d.month; day = d.day;}
~Date(){}
Date operator++(int){ //日期加1,重载后置++
switch (month)
{
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
if (day<31) {day += 1;}
else { day = 1; month += 1; }
break;
case 12:
if (day < 31) {
day += 1;
}
else {
day = 1;
month = 1;
year += 1;
}
break;
case 4:
case 6:
case 9:
case 11:
if (day < 30) {day += 1;}
else {
day = 1;
month += 1;
}
break;
case 2:
if (IsLeapYear(year)){
if (day < 29) day += 1;
else {
day = 1; month += 1;
}
}
else if (day<28){ day += 1; }
else
{
day = 1; month += 1;
}
break;
}
return *this;
}
Date operator--(int){
switch (month)
{
case 1:
if (day == 1) { year -= 1; month = 12; day = 31; }
else day -= 1;
break;
case 3:
if (day != 1) day -= 1;
else {
if (IsLeapYear(year)) { day = 29; month = 2; }
else { day = 28; month = 2; }
}
case 2:
case 4:
case 6:
case 8:
case 9:
case 11:
if (day != 1) day -= 1;
else { day = 31; month -= 1;}
break;
case 5:
case 7:
case 10:
case 12:
if (day != 1) day -= 1;
else { day = 30; month -= 1; }
break;
}
return *this;
}
Date operator+(int days) //days天之后的日期
{
Date temp(*this);
for (int i = 0; i < days; i++)
{
temp++;
}
return temp;
}
Date operator-(int days) //days天之前的日期
{
Date temp(*this);
for (int i = 0; i < days; i++)
{
temp--;
}
return temp;
}
bool IsLeapYear(int year){ //判断是否为闰年
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
{
return true;
}
return false;
}
void ShowDate(){ //显示日期,格式如2000-10-01
cout << year << "-" << month << "-" << day << endl;
}
};
int main(){
Date d1, d2(1999, 5, 25), d3;
cout << "d1日期:";
d1.ShowDate();
cout << "d2日期:";
d2.ShowDate();
d3=d1++;
cout << "d1日期++:";
d3.ShowDate();
d3 = d2--;
cout << "d2日期--:";
d3.ShowDate();
d3 = d1 + 20;
cout << "d1日期+20天:";
d3.ShowDate();
d3 = d2 - 20;
cout << "d2日期-20天:";
d3.ShowDate();
return 0;
}
运行结果: