date.h文件代码:
#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
class date
{
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)
{
_year = year;
_month = month;
_day = day;
if (!(*this).checkdate())
{
cout << "日期非法" << endl;
}
}
date(const date& d)//这是拷贝构造,当然对于这个类不需要显示的写拷贝构造。
{
_year = d._year;
_month = d._month;
_day = d._day;
}
void print();
int getmonthday(int year, int month)//这个函数是用来找到某年某月的天数的
{
assert(month >= 1 && month < 13);
static int monthday[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };//这里将数组用static修饰就是因为这个函数会被频繁的调用,为了避免每一次都要重新建立数组
if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
return 29;
else
return monthday[month];
}//这个函数需要频繁调用且函数简单,可以考虑弄成内联函数inline,当然写在类中的函数默认内联
date& operator+=(int day);//注意这里是+=不是+,语义保持一致
date operator+(int day);//对于加的实现
date& operator-=(int day);
date operator-(int day);
bool operator<(const date& d);
bool operator<=(const date& d);
bool operator>(const date& d);
bool operator>=(const date& d);
bool operator==(const date& d);
bool operator!=(const date& d);
date& operator++();//这个是前置++
date operator++(int);//这个是后置++
date& operator--();//这个是前置--
date operator--(int);//这个是后置--
date& operator=(const date& d);//这是赋值运算符重载。
int operator-(const date& d);//实现两个日期相减。
void operator<<(ostream& out);//这是对<<重载,注意cout的类型为ostream(out stream)
bool checkdate()
{
if ( _month >= 13 || _month <= 0 || _day <= 0 || _day>getmonthday(_year, _month))
return false;
else
return true;
}
private://成员变量
int _year;
int _month;
int _day;
};
//这里将operator<<重载为全局函数,来解决顺序问题。
ostream& operator<<(ostream& out, const date& d);
//注意这里写成ostream&的返回类型的原因跟operator=赋值操作符重载函数的原因类似,是为了连续的输出
istream& operator>>(istream& in, date& d);
date.cpp文件代码:
#define _CRT_SECURE_NO_WARNINGS
#include"date.h"
bool date::operator<(const date& d)
{
if (_year > d._year)
return false;
else
{
if (_year==d._year&&_month > d._month)
return false;
else
{
if (_month==d._month&&_day >= d._day)
return false;
else
return true;
}
}
}
bool date::operator<=(const date& d)
{
return !(*this > d);
}
bool date::operator>(const date& d)
{
if (_year < d._year)
return false;
else
{
if (_year==d._year&&_month < d._month)
return false;
else
{
if (_month==d._month&&_day <= d._day)
return false;
else
return true;
}
}
}
bool date::operator>=(const date& d)
{
return !(*this < d);
}
bool date::operator==(const date& d)
{
return (_year == d._year && _month == d._month && _day == d._day);
}
bool date::operator!=(const date& d)
{
return !(*this == d);
}
date& date::operator=(const date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
return *this;
}
date& date::operator+=(int day)
{
if (day < 0)
return *this -= (-day);
_day += day;
while (_day > getmonthday(_year, _month))
{
_day -= getmonthday(_year, _month);
_month++;
if (_month > 12)
{
_month -= 12;
_year++;
}
}
return *this;
}
date date::operator+(int day)
{
if (day < 0)
return *this - (-day);
date tmp = *this;
tmp._day += day;
while (tmp._day > getmonthday(tmp._year, tmp._month))
{
tmp._day -= getmonthday(tmp._year, tmp._month);
tmp._month++;
if (tmp._month > 12)
{
tmp._month -= 12;
tmp._year++;
}
}//其实可以利用+=函数,实现+
return tmp;
}//注意这里tmp出了函数就消失了,所以需要传值返回。
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);
}
return *this;
}
date date::operator-(int day)
{
date tmp = *this;
tmp -= day;
return tmp;
}
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;
}
int date::operator-(const date& d)
{
date max = *this;
date min = d;
int flag = 1;
int cha = 0;
if (max < min)
{
max = d;
min = *this;
flag = -1;
}
while (min != max)
{
++min;
++cha;
}
return flag * cha;
}
void date::operator<<(ostream& out)
{
out << _year << '/' << _month << '/' << _day << endl;
}
//以上是一些比较操作符重载函数。
void date::print()
{
std::cout << _year << '/' << _month << '/' << _day << std::endl;
}
ostream& operator<<(ostream& out, const date& d)//但是这里有又一个问题,我们无法在类外访问pravite中的变量。
//这里可以使用友元函数声明
//注意这里ostream类型的变量是不支持拷贝的,只能引用
{
out << d._year << '/' << d._month << '/' << d._day << endl;
return out;
}
istream& operator>>(istream& in, date& d)
{
while (1)
{
cout << "请依次输入年月日" << endl;
in >> d._year >> d._month >> d._day;
if (d.checkdate())
break;
else
cout << "日期非法,请重新输入:" << endl;
}
return in;
}
test.cpp测试文件代码:
#define _CRT_SECURE_NO_WARNINGS
#include"date.h"
int main()
{
date d1(2024, 8, 14);
date d2 = d1;
d1.print();
d2.print();
(d1 += 100).print();
(d1 -= 100).print();
(d1 += -7253).print();
(d2 -= -100).print();
(d1++).print();//打印的是++之前的值
d1.print();
(++d1).print();//打印的是++之后的值
date d4(2024, 8, 14);
date birthday(2004, 10, 5);
cout << birthday - d4 << endl;
d4 << cout;//注意这个二元的重载操作符的传参顺序是:
//操作符左边的传给左边,右边的传给右边,要将cout传给out,d4传给operator当this指针
cout << d4 << d1 << d2;//这个调用的是全局的操作符重载函数。
cin >> d1 >> d2;
cout << d1 << d2;
date d5(2023, 2, 29);
return 0;
}
下面是文中提到的一些细节:
如果觉得有帮助的话点个赞和关注,本人会尽快更新。