1.日期类局部实现
**局部实现中的代码只是一部分,不能正常运行。总体代码在最后。(总体代码在win10系统下的vs2019验证)**
(1)类中成员变量
日期类成员变量应该有:年,月,日。
代码一:成员变量应设置为 private 权限。
//代码一
class Date {
private:
int _year;
int _month;
int _day;
}
(2)判断输入日期合法函数
在进行对象的构造时,需要手动传入参数,但需要判断参数的合法性。
代码二:将每个月的天数设置为数组中的元素,在0下标位置设置占位符,这样从1开始,就可以直接将月份作为下标使用。**(如果日期合法返回true,否则返回false)**
//代码二
bool JudgeDay(int year,int month,int day) {
if (year < 0)
return false;
if (month > 12 || month < 1)
return false;
int Days[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
//如果是闰年,二月天数要加一
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
Days[2] += 1;
if (Days[month] >= day && day > 0)
return true;
else
return false;
}
(3)构造函数
代码三:使用判断函数的返回值作为条件,当日期非法,( **!JudgeDay(year,month,day)** )的值为true,进入条件。
//代码三
Date(int year = 2020,int month = 12,int day = 12)
:_year(year)
,_month(month)
,_day(day)
{
//当输入的日期不符合实际 JudgeDay返回false,通过取反进入选择语句
if (!JudgeDay(year,month,day)) {
_year = 2021;
_month = 1;
_day = 2;
}
}
(4)获取月份对应天数函数
代码四:
//代码四
int GetDay(int year,int month) {
int Days[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
Days[2] += 1;
return Days[month];
}
(5)拷贝构造函数
代码五:
//代码五
Date(const Date& d)
:_year(d._year)
,_month(d._month)
,_day(d._day)
{}
(6)赋值运算符重载
通过赋值运算符为另一个对象赋值。
代码六:注意:需要判断是否自己为自己赋值。
//代码六
Date& operator=(const Date& d) {
//判断是否是自己给自己赋值
if (this != &d) {
_year = d._year;
_month = d._month;
_day = d._day;
}
return *this;
}
(7)+运算符重载
代码七:+ 运算符重载时需要注意,注意在月份增加到13后要进行更新,年份加1,将月份重新设置为1月份。
同时,应使用拷贝构造函数构造一个临时变量进行计算,因为不可以改变初始的对象。
//代码七
Date operator+(int day) {
//此处复用了重载后的 -
if (day < 0) {
return *this - (0 - day);
}
Date temp(*this);
temp._day += day;
while (temp._day > GetDay(temp._year, temp._month)) {
//减去本月份应该拥有的天数
temp._day -= GetDay(temp._year, temp._month);
//将月份转到下个月
temp._month += 1;
if (temp._month > 12) {
temp._month %= 12;
temp._year += 1;
}
}
return temp;
}
(8)前置++运算符重载
代码八:需要符合前置++的运算规则,将本对象加1,然后将本对象返回。
//日期的更新,++
Date& operator++() {
*this = *this + 1;
return *this;
}
(9)后置++运算符重载
代码九:后置++运算规则,用本对象的现有值赋值,然后将本对象加一,所以需要先构造临时对象保存现有值。
** 注意:后置++重载时需要加上整型参数。**
//代码九
Date operator++(int x) {
Date temp(*this);
*this = *this + 1;
return temp;
}
(10)-运算符重载
代码十:重载 - 运算符时,首先需要在循环体内将月份减1,然后进行年份的更新,然后再根据月份更新天数。原因用一个例子解释:
假设目前是 2022年9月1日,减去30天(**9月30天,8月31天**),正确结果应该是2022年8月2日。那么运行完 ( **temp._day -= day; **) 后,就是2022年9月-29天。如果不先更新月份,而是先加日期(此时加的肯定就是9月的天数),再更新月份,最终结果就是,2022年8月1号。
//代码十
Date operator-(int day) {
//复用重载后的 + 运算符
if (day < 0) {
return *this + (0 - day);
}
Date temp(*this);
temp._day -= day;
while (temp._day <= 0) {
temp._month -= 1;
if (temp._month <= 0) {
temp._month = 12;
temp._year -= 1;
}
temp._day += GetDay(temp._year, temp._month);
}
return temp;
}
(11)前置--运算符重载
代码十一:和前置++类似
//代码十一
Date& operator--() {
*this = *this - 1;
return *this;
}
(12)后置--运算符重载
代码十二:和后置++类似
//代码十二
Date operator--(int x) {
Date temp(*this);
*this = *this - 1;
return temp;
}
(13)>运算符重载
代码十三:条件语句中的三个条件使用或运算。
第一个:左边年份大于右边。第二个:年份相同,左边月份大于右边。第三个:年月相同,左边日期大于右边。
//代码十三
//左边大,返回ture
bool operator>(const Date& d) {
if ((_year > d._year) || (_year == d._year && _month > d._month) || (_year == d._year && _month == d._month && _day > d._day)) {
return true;
}
else {
return false;
}
}
(14)<运算符重载
代码十四:当( ***this > d || *this == d** ),只要两个条件成立一个,说明左边不小于右边,表达式为false,通过取反,返回true。并且复用了重载后的 > 和 ==
//代码十四:
//复用 > 和 ==
bool operator<(const Date& d) {
return !(*this > d || *this == d);
}
(15)==运算符重载
代码十五:三个条件同时成立才相等,返回true
//代码十五
bool operator==(const Date& d) {
return (_year == d._year) && (_month == d._month) && (_day == d._day);
}
(16)!=运算符重载
代码十六:复用了重载后的 ==
//代码十六
//复用==
bool operator!=(const Date& d) {
return !(*this == d);
}
(17)输出运算符(<<)重载
观察平时如何使用:cout << (要输出的内容) ,有个缺点,只能直接打印内置类型,不能直接打印类类型,可以进行重载。**(注意 cout 也是一个对象,它是ostream的对象) **
<1>错误重载(重载为类的成员函数)
重载后的调用机制:cout.operator<<(this)
但如下的代码有错误,因为 类的成员函数会在第一个参数的位置隐含this指针,所以重载后不符合实际。实际上的操作顺序是 cout << this,重载后顺序 this << cout。这样的话,调用语句就应该是:对象名 << cout。
代码十七:
//代码十七
ostream& operator<<(ostream& _cout) {
cout << _year << "-" << _month << "-" << _day;
return _cout;
}
<2>正确重载(重载为全局函数)
为了解决上述问题,我们可以将它重载为全局函数,将cout对象的参数放在首位。
原本的 << 还具有连续输出功能,所以我们需要用一个返回值来完成这个功能,连续调用的机制:举例,cout << a << b。实际上是,( cout.operator<<(a) ) . operator << ( b )。将cout.operator<<(a) 的返回值(cout)再一次作为参数。
代码十八:这样才是正确重载,但它有一个问题,成员变量已经设置为private,无法在类外直接访问,我们通过友元函数解决,目前只需要知道如何使用友元就好。
//代码十八
ostream& operator<<(ostream & _cout,Date& d) {
cout << d._year << "-" << d._month << "-" << d._day;
return _cout;
}
** 友元:如果你想让类外函数A使用类B中的全部成员(任何访问权限),就将A设置为B的友元函数。**
语法:**friend 函数声明**
代码十九:
//代码十九
class Date {
friend ostream& operator<<(ostream & _cout,Date& d) ;
private:
int _year;
int _month;
int _day;
}
2.日期类总体实现
#include "iostream"
using namespace std;
class Date {
friend ostream& operator<<(ostream& _cout, Date& d);
private:
int _year;
int _month;
int _day;
public:
//构造函数
Date(int year = 2020,int month = 12,int day = 12)
:_year(year)
,_month(month)
,_day(day)
{
//当输入的日期不符合实际 JudgeDay返回false,通过取反进入选择语句
if (!JudgeDay(year,month,day)) {
_year = 2021;
_month = 1;
_day = 2;
}
}
//判断构造函数中输入的Day变量是否符合实际
bool JudgeDay(int year,int month,int day) {
if (year < 0)
return false;
if (month > 12 || month < 1)
return false;
int Days[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
//如果是闰年,二月天数要加一
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
Days[2] += 1;
if (Days[month] >= day && day > 0)
return true;
else
return false;
}
//得到对应天数
int GetDay(int year,int month) {
int Days[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
Days[2] += 1;
return Days[month];
}
//拷贝构造函数
Date(const Date& d)
:_year(d._year)
,_month(d._month)
,_day(d._day)
{}
//赋值运算符重载
Date& operator=(const Date& d) {
//判断是否是自己给自己赋值
if (this != &d) {
_year = d._year;
_month = d._month;
_day = d._day;
}
return *this;
}
//+运算符重载,计算x天后的日期
Date operator+(int day) {
if (day < 0) {
return *this - (0 - day);
}
Date temp(*this);
temp._day += day;
while (temp._day > GetDay(temp._year, temp._month)) {
temp._day -= GetDay(temp._year, temp._month);
temp._month += 1;
if (temp._month > 12) {
temp._month %= 12;
temp._year += 1;
}
}
return temp;
}
//-运算符重载,计算x天前的日期
Date operator-(int day) {
//复用重载后的 + 运算符
if (day < 0) {
return *this + (0 - day);
}
Date temp(*this);
temp._day -= day;
while (temp._day <= 0) {
temp._month -= 1;
if (temp._month <= 0) {
temp._month = 12;
temp._year -= 1;
}
temp._day += GetDay(temp._year, temp._month);
}
return temp;
}
//-运算符重载,计算两个日期对象之间差多少天
int operator-(const Date& d) {
Date minDate(*this);
Date maxDate(d);
if (minDate > maxDate) {
minDate = d;
maxDate = *this;
}
int count = 0;
while (minDate != maxDate) {
count++;
minDate++;
}
return count;
}
// >重载
//this大,返回ture
bool operator>(const Date& d) {
if ((_year > d._year) || (_year == d._year && _month > d._month) || (_year == d._year && _month == d._month && _day > d._day)) {
return true;
}
else {
return false;
}
}
// <重载
//复用>
bool operator<(const Date& d) {
return !(*this > d || *this == d);
}
bool operator==(const Date& d) {
return (_year == d._year) && (_month == d._month) && (_day == d._day);
}
// != 重载
//复用==
bool operator!=(const Date& d) {
return !(*this == d);
}
//前置++重载
Date& operator++() {
*this = *this + 1;
return *this;
}
//后置++重载
Date operator++(int x) {
Date temp(*this);
*this = *this + 1;
return temp;
}
//前置--重载
Date& operator--() {
*this = *this - 1;
return *this;
}
//后置--重载
Date operator--(int x) {
Date temp(*this);
*this = *this - 1;
return temp;
}
};
//<<重载为全局函数
ostream& operator<<(ostream & _cout,Date& d) {
cout << d._year << "-" << d._month << "-" << d._day;
return _cout;
}
int main() {
Date d1(2022, 1, 1);
cout << "d1:" << d1 << endl;//输出 d1:2022-1-1
Date d2 = d1;
cout << "d2:" << d2 << endl;//输出 d2:2022-1-1
Date d3 = d1 - 100;
cout << "d3:" << d3 << endl;//输出 d3:2021-9-23
cout << "d3 - d1:" << d3 - d1 << endl;//输出 d3 - d1:100
}
标签:
c++
本文转载自: https://blog.csdn.net/weixin_57761086/article/details/126482723
版权归原作者 爱喝酸奶! 所有, 如有侵权,请联系我们删除。
版权归原作者 爱喝酸奶! 所有, 如有侵权,请联系我们删除。