一、目标
通过前面对类和对象的介绍我们可以自己通过C++代码初步实现一个简单的日期类。
实现的主要操作有:
1.日期类的构造函数
2.日期类的拷贝构造函数(在头文件中实现)
3.日期类的比较运算符重载
4.日期类的计算运算符重载
5.流插入运算符重载。
二、总体思路
首先,我这里采用的是分文件编程的方式来实现的日期类。
分别为:
1.头文件:Date.h
该文件的主要目的是对上述目标所要实现的所有操作进行函数的声明。同时,还要包含在
源文件Date.cpp 中定义时所需要用到的头文件函数。
2.源文件:Date.cpp
该文件的目的主要是用于对 头文件Date.h 所声明的所有函数进行定义,从而完成各个函数所要实现的操作。
3.源文件:Test.cpp
该文件的目的主要是用于检测 源文件Date.cpp 中定义的函数是否能正常够使用并且达到所要实现的操作。
三、代码实现及具体思路
1.头文件:Date.h
通过上面思路的介绍,我们可以知道,我们的目的是创建一个日期类,然后在日期类中自我声明:日期类的构造函数、日期类的比较运算符重载、日期类的计算运算符重载以及流插入运算符重载。并实现拷贝构造函数。
(注意:通过我们前面对类和对象的介绍可知,因为在实现日期类过程中,我们没有动态申请空间,所以我们只需使用编译器默认生成的析构函数就可以,因此,我们不需要自己再定义一个析构函数)
代码如下:
#pragma once
#include <iostream>
#include <assert.h>
using namespace std;
class Date
{
public:
Date(int year = 1, int month = 1, int day = 1);
void Print()const
{
cout << _year << '-' << _month << '-' << _day << endl;
}
Date(const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
//日期类的比较运算符的重载
bool operator<(const Date& x) const;
bool operator==(const Date& x) const;
bool operator<=(const Date& x) const;
bool operator>(const Date& x) const;
bool operator>=(const Date& x) const;
bool operator!=(const Date& x) const;
//日期类的计算运算符的重载
int Get_MonthDay(int year,int month); //获取该月份的天数
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& x) const;
// 流插入不能写成成员函数?
// 因为Date对象默认占用第一个参数,就是做了左操作数
// 写出来就一定是下面这样子,不符合使用习惯
//d1 << cout; // d1.operator<<(cout);
//void operator<<(ostream& out);
// 友元函数声明
friend ostream& operator<<(ostream& out, const Date& d);
friend istream& operator>>(istream& in, Date& d);
private:
int _year;
int _month;
int _day;
};
ostream& operator<<(ostream& out, const Date& x);
istream& operator>>(istream& in, Date& x);
2.源文件:Date.cpp
对于实现下面函数,我们需要首先定义一个获取当前月份天数的函数
代码实现:
//因为平年闰年的2月天数不一样所以我们需定义一个获取月份的函数来解决这一问题
int Date::Get_MonthDay(int year, int month) //获取该月份的天数
{
static int daysArr[13] = { 0,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 daysArr[month];
}
}
1.日期类的构造函数
思路:
我们在通过日期类构造函数初始化所定义的日期时,我们需要判断我们所定义的日期是否合法,若不合法,则需要返回并提示
代码实现:
Date::Date(int year, int month, int day)
{
//判断所初始化的日期是否合法
if (month > 0 && month < 13
&&day>=1&&day<= Get_MonthDay(year, month))
{
_year = year;
_month = month;
_day = day;
}
else
{
cout << "非法日期" << endl;
assert(false);
}
}
2.日期类的比较运算符重载
思路:
对于比较类的运算符重载来说,因为比较运算符具有互斥性,所以我们只需定义出 < 运算符重载和 == 运算符重载,然后其他运算符复用上面所定定义的两个运算符即可。并且在比较的同时,我们不会改变参数的值,所以我们可以在函数尾部加const用于修饰内部的this指针,这样的话,const修饰的类型我们也可以通过比较运算符来比较。
代码实现:
bool Date::operator<(const Date& x) const
{
if (_year < x._year)
{
return true;
}
else if (_year == x._year && _month < x._month)
{
return true;
}
else if (_year == x._year && _month == x._month && _day < x._day)
{
return true;
}
else
{
return false;
}
}
bool Date::operator==(const Date& x) const
{
if (_year == x._year && _month == x._month && _day == x._day)
{
return true;
}
else
{
return false;
}
}
bool Date::operator<=(const Date& x) const
{
//复用上面定义的重载运算符:< , ==
return *this < x || *this == x;
}
bool Date::operator>(const Date& x) const
{
//复用上面定义的重载运算符:<=
return !(*this <= x);
}
bool Date::operator>=(const Date& x) const
{
//复用上面定义的重载运算符:> , ==
return *this > x || *this == x;
}
bool Date::operator!=(const Date& x) const
{
//复用上面定义的重载运算符:==
return !(*this == x);
}
3.日期类的计算运算符重载
思路:
对于日期类的计算运算符重载的定义,我们可以先定义 += 运算符重载和 -= 运算符重载,然后其他运算符重载的定义我们可以复用这两个运算符重载,从而实现各个运算符所要实现的目的。
代码实现:
Date& Date::operator+=(int day)
{
if (day < 0)
{
return *this -= (-day);
}
_day = _day + day;
while (_day > Get_MonthDay(_year, _month))
{
_day = _day-Get_MonthDay(_year, _month);
++_month;
if (_month == 13)
{
_month = 1;
++_year;
}
}
return *this;
}
Date Date::operator+(int day)const
{
if (day < 0)
{
return *this - (-day);
}
//复用上面定义的重载运算符:+=
Date tem(*this);
tem+= day;
return tem;
}
Date& Date::operator-=(int day)
{
if (day < 0)
{
return *this += (-day);
}
_day = _day - day;
while (_day < 1)
{
--_month;
if (_month <1 )
{
_month = 12;
--_year;
}
_day = _day + Get_MonthDay(_year, _month);
}
return *this;
}
Date Date::operator-(int day)const
{
if (day < 0)
{
return *this + (-day);
}
//复用上面定义的重载运算符:-=
Date tem(*this);
tem -= day;
return tem;
}
Date& Date::operator++()
{
//复用上面定义的重载运算符:+=
*this += 1;
return *this;
}
Date Date::operator++(int)
{
//复用上面定义的重载运算符:+
Date tem = *this;
*this += 1;
return tem;
}
Date& Date::operator--()
{
//复用上面定义的重载运算符:+=
*this -= 1;
return *this;
}
Date Date::operator--(int)
{
//复用上面定义的重载运算符:+
Date tem = *this;
*this -= 1;
return tem;
}
实现两个日期之间相减求天数时,我们可以先判断哪个日期大,从而确定出所求的天数是正数还是负数,即用flage的正负来实现。接着我们定义一个n来统计天数,然后我们通过while循环,++最小的日期,并且++天数直到最小日期和最大日期相等的时候结束,这时候我们返回n*flage的值即是所求天数。
int Date::operator-(const Date& x) const
{
Date max = *this;
Date min = x;
int flage = 1;
if (*this < x)
{
max = x;
min = *this;
flage = -1;
}
int n = 0;
while (min != max)
{
++min;
++n;
}
return n * flage;
}
4.流插入运算符重载。
思路:
对于日期类使用系统中的流插入(只能插入内置类型)时并不能实现所期望的操作,因为日期类是自定义类型,所以我们就需要自己定义一个流插入来实现这个操作
// 流插入不能写成成员函数?
// 因为Date对象默认占用第一个参数,就是做了左操作数
// 写出来就一定是下面这样子,不符合使用习惯
//d1 << cout; // d1.operator<<(cout);
//void operator<<(ostream& out);
因此,这里我们通过友元函数,在全局中定义流插入的运算符重载
代码实现:
ostream& operator<<(ostream& out, const Date& x)
{
out << x._year << "年" << x._month << "月" << x._day << "日" << endl;
return out;
}
istream& operator>>(istream& in, Date& x)
{
int year, month, day;
in >> year >> month >> day;
if (month > 0 && month < 13
&& day > 0 && day <= x.Get_MonthDay(year, month))
{
x._year = year;
x._month = month;
x._day = day;
}
else
{
cout << "非法日期" << endl;
assert(false);
}
return in;
}
3.源文件:Test.cpp
Test1:
用于检测日期类的比较运算符的重载
void Test1() //用于检测日期类的比较运算符的重载
{
Date s1(2005, 2, 16);
Date s2(2024, 8, 12);
cout << "bool operator<(const Date& x) const:" << (s1 < s2) << endl;
cout << "bool operator==(const Date& x) const:" << (s1 == s2) << endl;
cout << "bool operator<=(const Date& x) const:" << (s1 <= s2) << endl;
cout << "bool operator>(const Date& x) const:" << (s1 > s2) << endl;
cout << "bool operator>=(const Date& x) const:" << (s1 >= s2) << endl;
cout << "bool operator!=(const Date& x) const:" << (s1 != s2) << endl;
}
Test2:
用于检测日期类的计算运算符的重载:+= , +
void Test2() //用于检测日期类的计算运算符的重载:+= , +
{
Date s1(2005, 2, 16);
s1.Print();
s1 += 10000;
s1.Print();
Date s2(2005, 2, 16);
s2.Print();
Date s3=s2+10000;
s3.Print();
}
Test3:
用于检测日期类的计算运算符的重载:-= , -
void Test3() //用于检测日期类的计算运算符的重载:-= , -
{
Date s1(2005, 2, 16);
s1.Print();
s1 -= 1000;
s1.Print();
Date s2(2005, 2, 16);
s2.Print();
Date s3 = s2 - 1000;
s3.Print();
}
Test4:
用于检测日期类的计算运算符的重载:--
void Test4() //用于检测日期类的计算运算符的重载:--
{
Date s2(2005, 2, 16);
Date s3(2005, 2, 16);
Date s4;
s4=s2--;
s4.Print();
s4 = --s3;
s4.Print();
}
Test5:
用于检测日期类的计算运算符的重载:++
void Test5() //用于检测日期类的计算运算符的重载:++
{
Date s2(2005, 2, 16);
Date s3(2005, 2, 16);
Date s4;
s4 = s2++;
s4.Print();
s4 = ++s3;
s4.Print();
}
Test6:
用于检测日期类之间的计算运算符的重载:-
void Test6() //用于检测日期类之间的计算运算符的重载:-
{
Date s1(2005, 2, 16);
Date s2(2024, 8, 13);
cout << "int operator-(const Date& x) const:" << (s1 - s2) << endl;
}
Test7:
用于检测日期类之间的计算运算符的重载:<< , >>
void Test7() //用于检测日期类之间的计算运算符的重载:<< , >>
{
Date s1;
cin >> s1;
cout << s1 << endl;
cout << s1 + 100 << endl;
}
四、结语:
上述内容,即是我个人对C++日期类的个人见解及代码实现。若有大佬发现哪里有问题可以私信或评论指教一下。非常感谢各位uu们的点赞,关注,收藏,还望各位多多关照,让我们一起进步吧!