文章目录
前言
1日期类的成员变量
class Date
{
public:
void Print()//这里可以先写一个打印函数,方便我们测试
{
cout << _year << "-" << _month << "-" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
2检查日期合法性函数
//检查日期合法性
bool Date::CheckDate()
{
if (_month < 1 || _month > 12
|| _day < 1 || _day > GetMonthDay(_year, _month))
{
return false;
}
else
{
return true;
}
}
3获取每年每月的天数
//定义函数用来获取每年每月的天数
int GetMonthDay(int year, int month)
{
assert(month > 0 && month < 13);
static int arr[13][2] = { {-1,-1},{31,31},{28,29},{31,31},
{30,30},{31,31},{30,30},{31,31},
{31,31},{30,30},{31,31},{30,30},{31,31} };
if ((_year % 4 == 0 && _year % 100 != 0) || _year % 400 == 0)
{
return arr[month][1];
}
return arr[month][0];
}
一、默认成员函数
1.1构造函数
//构造函数
Date::Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
if (!CheckDate())
{
cout << "日期非法->";
cout << *this << endl;
}
}
1.2析构函数
对于日期类来说,编译器i默认的析构函数就能帮我们解决日期类析构的需求,所以
不需要显式写。
析构函数的相关知识,请参考
析构函数
1.3拷贝构造函数
对于日期类来说,编译器i默认的拷贝构造函数就能帮我们解决日期类拷贝构造的需求,所以
不需要显式写。
拷贝构造函数的相关知识,请参考
拷贝构造函数
1.4运算符重载
1.4.1赋值运算符重载
Date& Date::operator=(const Date& d)
{
if (this != &d)//自己拷贝给自己,则直接返回
{
_year = d._year;
_month = d._month;
_day = d._day;
}
return *this;
}
1.4.2比较运算符重载
- 小于
bool Date::operator<(const Date& d)
{
if (_year < d._year)
{
return true;
}
else if (_year == d._year && _month < d._month)
{
return true;
}
else if (_year == d._year
&& _month == d._month
&& _day < d._day)
{
return true;
}
else
{
return false;
}
}
- 等于
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 || *this == d;
}
- 大于(
因为前面我们已经对小于等于进行了重载,所以这里可以直复用
)
bool Date::operator>(const Date& d)
{
//因为前面我们已经对小于等于进行了重载,所以这里可以直复用
return !(*this <= d);
}
- 大于等于(
因为前面我们已经对小于进行了重载,所以这里可以直复用
)
bool Date::operator>=(const Date& d)
{
//因为前面我们已经对小于进行了重载,所以这里可以直复用
return !(*this < d);
}
- 不等于(
因为前面我们已经对等于进行了重载,所以这里可以直复用
)
bool Date::operator!=(const Date& d)
{
return !(*this == d);
}
1.4.3日期加减天数
- 加等(+=)
Date& Date::operator+=(int day)
{
if (day < 0)//如果加的天数是负数,直接调用-=
{
return *this -= -day;
}
_day = day + _day;
//加完的天数超出本月天数的上限,进入循环
while (_day > GetMonthDay(_year, _month))
{
_day = _day - GetMonthDay(_year, _month);
_month = _month % 12;
if (_month == 0)
{
_year++;
}
_month++;
}
return *this;
}
- 加(+)
Date Date::operator+(int day)
{
Date temp = *this;
temp += day;//复用+=
return temp;
}
- 减等
Date& Date::operator-=(int day)
{
if (day < 0)
{
return *this += -day;
}
_day = _day - day;
while (_day < 1)
{
_month--;
if (_month == 0)
{
_year--;
_month = 12;
}
_day = _day + GetMonthDay(_year, _month);
}
return *this;
}
- 减(-)
Date Date::operator-(int day)
{
Date temp = *this;
temp -= day;
return temp;
}
1.4.4自增和自减
前置++
(++d)
Date& Date::operator++()
{
return *this += 1;
}
后置++
(d++)
Date Date::operator++(int)
{
Date temp = *this;
*this += 1;
return temp;
}
前置--
(–d)
Date& Date::operator--()
{
return *this -= 1;
}
后置--
(d–)
Date Date::operator--(int)
{
Date temp = *this;
*this -= 1;
return temp;
}
1.4.5日期 - 日期
对于日期类来说,日期加日期没有意义
//日期-日期
int Date::operator-(const Date& d)
{
Date max = *this;
Date min = d;
int flag = 1;
if (*this < d)
{
max = d;
min = *this;
flag = -1;
}
int count = 0;
while (min != max)
{
min++;
count++;
}
return count * flag;
}
1.4.6<<和>>重载
- 重载<<和>>时,需要重载为全局函数,因为重载为成员函数,this指针默认抢占了第⼀个形参位置,第⼀个形参位置是左侧运算对象,调⽤时就变成了对象<<cout,不符合使⽤习惯和可读性。如下面的代码所示:
void Date::operator<<(ostream& out)
{
out << _year << "年" << _month << "月" << _day << "日" << endl;
}
int main()
{
Date d(2024,10,1);
//输出打印d,不符合使⽤习惯和可读性
d<<cout;//正常来说应该是 cout<<d
return 0;
}
- 重载为全局函数把ostream/istream放到第⼀个形参位置就可以了,第⼆个形参位置当类类型对象。
但重载为全局函数时,又会面临一个问题,那就是成员变量是私有的不允许全局访问。那我们再引入友元的概念
举个例子
:你家有一块羽毛球场地,是你私有的别人不能用。但是呢你规定你的朋友可以来使用。所以友元的友也就是朋友的意思。
友元私有还是公有无所谓。
//>>输出
class Date
{
//友元函数声明
friend ostream& operator<<(ostream& out, const Date& d);
public:
//....
private:
int _year;
int _month;
int _day;
};
//<<(定义为全局函数)
ostream& operator<<(ostream& out, const Date& d)
{
out << d._year << "年" << d._month << "月" << d._day << "日" << endl;
return out;
}
<<插入
class Date
{
//友元函数声明
friend istream& operator>>(istream& in, Date& d);
friend ostream& operator<<(ostream& out, const Date& d);
public:
//....
private:
int _year;
int _month;
int _day;
};
//>>
istream& operator>>(istream& in, Date& d)
{
while (1)
{
cout << "请输入年月日->:";
in >> d._year >> d._month >> d._day;
if (d.CheckDate())
{
break;
}
else
{
cout << "日期不合法,重新输入" << endl;
}
}
return in;
}
二、完整代码
这里有些函数用const修饰,至于原因,请参考下面的文章:
取地址运算符重载
2.1头文件(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 = 2002, int month = 1, int day = 9);
void Print() const;
int GetMonthDay(int year, int month) const
{
assert(month > 0 && month < 13);
static int arr[13][2] = { {-1,-1},{31,31},{28,29},{31,31},{30,30},{31,31},{30,30},{31,31},{31,31},{30,30},{31,31},{30,30},{31,31} };
if ((_year % 4 == 0 && _year % 100 != 0) || _year % 400 == 0)
{
return arr[month][1];
}
return arr[month][0];
}
//检查日期合法性
bool CheckDate() const;
Date& operator=(const Date& d);
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;
Date& operator++();//前置++
Date operator++(int);//后置++
Date& operator--();//前置
Date operator--(int);//后置
//日期-日期
int operator-(const Date& d) const;
//<<
//void operator<<(ostream& out);
private:
int _year;
int _month;
int _day;
};
//<<
ostream& operator<<(ostream& out, const Date& d);
//>>
istream& operator>>(istream& in, Date& d);
2.2源文件(Date.cpp)
#define _CRT_SECURE_NO_WARNINGS 1
#include"Date.h"
//构造函数
Date::Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
if (!CheckDate())
{
cout << "日期非法->:";
cout << *this << endl;
}
}
//检查日期合法性
bool Date::CheckDate() const
{
if (_month < 1 || _month > 12
|| _day < 1 || _day > GetMonthDay(_year, _month))
{
return false;
}
else
{
return true;
}
}
Date& Date::operator=(const Date& d)
{
if (this != &d)//自己拷贝给自己,则直接返回
{
_year = d._year;
_month = d._month;
_day = d._day;
}
return *this;
}
void Date::Print() const
{
cout << _year << "-" << _month << "-" << _day << endl;
}
bool Date::operator<(const Date& d) const
{
if (_year < d._year)
{
return true;
}
else if (_year == d._year && _month < d._month)
{
return true;
}
else if (_year == d._year
&& _month == d._month
&& _day < d._day)
{
return true;
}
else
{
return false;
}
}
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);
}
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);
}
Date& Date::operator+=(int day)
{
if (day < 0)//如果加的天数是负数,直接调用-=
{
return *this -= -day;
}
_day = day + _day;
//加完的天数超出本月天数的上限,进入循环
while (_day > GetMonthDay(_year, _month))
{
_day = _day - GetMonthDay(_year, _month);
_month = _month % 12;
if (_month == 0)
{
_year++;
}
_month++;
}
return *this;
}
Date Date::operator+(int day) const
{
Date temp = *this;
temp += day;//复用+=
//temp._day = day + temp._day;
//while (temp._day > GetMonthDay(temp._year, temp._month))
//{
// temp._day = temp._day - GetMonthDay(temp._year, temp._month);
// temp._month = temp._month % 12;
// if (temp._month == 0)
// {
// temp._year++;
// }
// temp._month++;
//}
return temp;
}
Date& Date::operator-=(int day)
{
if (day < 0)
{
return *this += -day;
}
_day = _day - day;
while (_day < 1)
{
_month--;
if (_month == 0)
{
_year--;
_month = 12;
}
_day = _day + GetMonthDay(_year, _month);
}
return *this;
}
Date Date::operator-(int day) const
{
Date temp = *this;
temp -= day;
return temp;
}
Date& Date::operator++()
{
return *this += 1;
}
Date Date::operator++(int)
{
Date temp = *this;
*this += 1;
return temp;
}
Date& Date::operator--()
{
return *this -= 1;
}
Date Date::operator--(int)
{
Date temp = *this;
*this -= 1;
return temp;
}
//日期-日期
int Date::operator-(const Date& d) const
{
Date max = *this;
Date min = d;
int flag = 1;
if (*this < d)
{
max = d;
min = *this;
flag = -1;
}
int count = 0;
while (min != max)
{
min++;
count++;
}
return count * 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 << "请输入年月日->:";
in >> d._year >> d._month >> d._day;
if (d.CheckDate())
{
break;
}
else
{
cout << "日期不合法,重新输入" << endl;
}
}
return in;
}
2.3测试函数(test.cpp)
这里只是我的一些测试,大家可以对日期类的操作进行各种测试
#define _CRT_SECURE_NO_WARNINGS 1
#include"Date.h"
int main()
{
Date d1(2002, 1, 9);
d1.Print();
d1 = d1 + 8304;
d1.Print();
d1 -= 8000;
d1.Print();
(d1++).Print();
(++d1).Print();
Date d2(2002, 1, 9);
Date d3(2024, 10, 4);
int day = d3 - d2;
printf("相差%d天\n", day);
Date d4(2024, 4, 14);
Date d5 = d4 + 30000;
// operator<<(cout, d1)
cout << d4;
cout << d5;
cin >> d4 >> d5;
cout << d4 << d5;
return 0;
}
2.4测试结果
总结
以上就是日期类的实现,也算是对前面几节的总结和应用。
今天也是国庆假期,祝我们国庆节快乐,祝祖国母亲繁荣昌盛。祝祖国统一指日可待。