目录
1、Date.h
2、注意
3、Date.cpp 实现
4、test.cpp 测试用例
日期类的实现是为了巩固C++初阶——类和对象(上)(中)的知识点
1、Date.h
#pragma once
#include <iostream>
using namespace std;
#include <assert.h>class Date
{// 友元函数,C++初阶——类和对象(下)friend ostream& operator<<(ostream& out, const Date& d);friend istream& operator>>(istream& in, Date& d);
public:// 全缺省的构造函数Date(int year = 1900, int month = 1, int day = 1);// 拷贝构造函数// d2(d1)Date(const Date& d);// 赋值运算符重载// d2 = d3 -> d2.operator=(&d2, d3)Date& operator=(const Date& d);// 析构函数~Date();// 获取某年某月的天数int GetMonthDay(int year, int month) const{assert(month > 0 && month < 13);int month_arr[] = { -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))// month == 2 更容易判断return 29;elsereturn month_arr[month];}bool CheckDate() const;void Print() const;// 日期+=天数Date& operator+=(int day);// 日期+天数Date operator+(int day) const;// 日期-天数Date operator-(int day) const;// 日期-=天数Date& operator-=(int day);// 前置++Date& operator++();// 后置++Date operator++(int);// 后置--Date operator--(int);// 前置--Date& operator--();// >运算符重载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;// 日期-日期 返回天数int operator-(const Date& d) const;
private:int _year;int _month;int _day;
};ostream& operator<<(ostream& out, const Date& d);
istream& operator>>(istream& in, Date& d);
2、注意
对象可以调用类里的函数,类里的函数也调用类里的函数
默认构造函数的声明处有缺省值,定义处没有,防止声明和定义的缺省值不一致。
Date类没有需要释放的资源,所以不用显示实现析构函数,拷贝构造函数,赋值运算符重载函数。
GetMonthDay(_year,_month) const
在类里成员函数默认为inline(多次调用的少量代码),const 使this指向的内容不能改变,声明定义一致加const。
日期-天数是,不够,借的是上个月的天数。
对_month,++--后都要进行判断。
因为 日期-天数 和 日期-=天数,非常相似,-调用了-=,进行复用,
其实也可以-=调用-,但多了两次拷贝构造和一次赋值
左-=调用- 右-调用-=
对于比较运算符,可以先实现完>和=或者<和=,根据逻辑运算符,可以进行复用。
日期-日期,由于一般日期的就是几千年,及计算机CPU运算速度很快(上亿次),所以不用担心效率问题。
重载<<和>>时,
若为成员函数,this指针抢占第一个参数的位置,只能 对象<<cout调用,不符合习惯,
所以作为全局函数,在类里将其声明为友元函数,即可使用对象的私有成员。
cout cin不支持拷贝构造,所以进行引用传递。
3、Date.cpp 实现
#include "date.h"bool Date::CheckDate() const
{if (_month < 1 || _month>12 || _day<1 || _day>GetMonthDay(_year, _month))return false;elsereturn true;
}void Date::Print() const
{cout << _year << '/' << _month << '/' << _day << endl;
}// 全缺省的构造函数
Date::Date(int year, int month, int day)// 只在声明处给缺省值,防止声明和定义的缺省值不一致
{_year = year;_month = month;_day = day;if (!CheckDate())// 成员函数,默认前面有this.,第一个参数为this{cout << "非法日期";Print();}
}// 拷贝构造函数
// d2(d1)
Date::Date(const Date& d)
{_year = d._year;_month = d._month;_day = d._day;
}// 赋值运算符重载
// d2 = d3 -> d2.operator=(&d2, d3)
Date& Date::operator=(const Date& d)
{_year = d._year;_month = d._month;_day = d._day;return *this;
}// 析构函数
Date::~Date()
{;//无资源释放
}// 日期+=天数
Date& Date::operator+=(int day)
{if (day < 0){*this -= (-day);}else{_day += day;// 日期变了int d;while (_day > (d = GetMonthDay(_year, _month)))// 其实是this->GetMonthDay(){_day -= d;// 减这个月的天数++_month;if (_month > 12){_month = 1;++_year;}}}return *this;// 日期对象出了函数还存在,传引用返回,减少拷贝
}// 日期+天数
Date Date::operator+(int day) const
{Date tmp = *this;// 日期没有变tmp += day;return tmp;// tmp为局部变量,值返回
}// 日期-=天数
Date& Date::operator-=(int day)
{if (day < 0){*this += (-day);}else{_day -= day;// 日期变了while (_day <= 0){--_month;// 加上个月的天数,因为要借上个月的天数if (_month < 1){_month = 12;--_year;}_day += GetMonthDay(_year, _month);}}return *this;// 日期对象出了函数还存在,传引用返回,减少拷贝
}// 日期-天数
Date Date::operator-(int day) const
{Date tmp = *this;// 日期没有变tmp -= day;return tmp;// tmp为局部变量,值返回
}// 前置++
Date& Date::operator++()
{*this = *this + 1;return *this;
}// 后置++
Date Date::operator++(int)
{Date tmp = *this;*this = *this + 1;return tmp;
}// 前置--
Date& Date::operator--()
{*this = *this - 1;return *this;
}// 后置--
Date Date::operator--(int)
{Date tmp = *this;*this = *this - 1;return tmp;
}// >运算符重载
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;}return false;
}// ==运算符重载
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 *this > d || *this == d;
}// <运算符重载
bool Date::operator < (const Date& d) const
{return !(*this >= d);
}// <=运算符重载
bool Date::operator <= (const Date& d) const
{return *this < d || *this == d;
}// !=运算符重载
bool Date::operator != (const Date& d) const
{return !(*this == d);
}// 日期-日期 返回天数
// *this-d
int Date::operator-(const Date& d) const
{int flag = -1;Date min = *this;Date max = d;if (max < min){flag = 1;min = d;max = *this;}int n = 0;while (min<max){++min;++n;}return n * flag;
}ostream& operator<<(ostream& out, const Date& d)
{out << d._year << '/' << d._month << '/' << d._day << endl;return out;
}istream& operator>>(istream& in, Date& d)
{while (1){cout << "请依次输入年月日:>";//不用担心会被读到,cin会刷新cout的缓冲区in >> d._year >> d._month >> d._day;if (!d.CheckDate()){cout << "输入非法日期:";d.Print();cout << "请输入正确日期!!!" << endl;}else{break;}}return in;
}
4、test.cpp 测试用例
#include "date.h"void test1()
{Date d1(2024, 11, 16);Date d2(d1);Date d3;d3 = d1;d1.Print();d2.Print();d3.Print();//d1 += 10000;//d2 -= 10000;//d1.Print();//d2.Print();//d1 += -10000;//d2 -= -10000;//d1.Print();//d2.Print();//d2 = d1 + -10000;//d2.Print();//d3 = d1 + 10000;//d3.Print();
}void test2()
{Date d1(2024, 11, 16);Date d2(2024, 11, 16);d1.Print();d2.Print();Date ret1 = d1++;ret1.Print();d1.Print();Date ret2 = ++d2;ret2.Print();d2.Print();
}void test3()
{Date d1(2024, 11, 16);Date d2(2024, 7, 12);d1.Print();d2.Print();cout << d1 - d2 << endl;
}void test4()
{Date d1, d2;cin >> d1 >> d2;cout << d1 << d2 << endl;cout << d1 - d2 << endl;
}int main()
{test4();return 0;
}