目录
日期类的整体结构
获得当月的天数
构造函数
打印函数
拷贝构造函数
重载赋值运算符=
重载小于运算符<
重载全等于运算符==
重载小于等于运算符<=
重载大于运算符>
重载大于等于运算符>=
重载不等于运算符!=
重载加等运算符+=
重载加法运算符+
重载减等运算符-=
重载减法运算符-(日期-天数)
重载前置++和后置++运算符的规定
重载前置++运算符
重载后置++运算符
重载前置--运算符
重载后置--运算符
重载减法运算符-(日期-日期)
日期类的整体结构
class Data
{
public:// 功能函数......private:int _year;int _month;int _day;
};
private 修饰的是成员变量,是被保护且不能在类外被访问的
public 中的成员函数是公开的,是可以在类外面调用的,接下来主要实现的就是日期类所需要的成员函数
获得当月的天数
int GetMonthDay(int year, int month)
{// 下标对应月份static int monthArray[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };// 4年一润,100年不润,400年一润if ((month == 2) && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))){return monthArray[month] + 1;}return monthArray[month];
}
测试代码:
构造函数
Data(int year = 1946, int month = 2, int day = 15)
{_year = year;_month = month;_day = day;// 判断年月日是否合法if (year < 0 ||month < 1 || month > 12 ||day < 1 || day > GetMonthDay(year, month)){cout << "非法日期" << endl;// 结束程序exit(-1);}
}
构造函数是类的默认成员函数,构造函数的作用可以充当初始化,会自动调用,以免忘记初始化
这里是全缺省的初始化,能在实例化日期类对象时更灵活
灵活的体现在于:
int main()
{Data d1; //不给参数Data d2(2024); //给一个参数Data d3(2024, 12); //给两个参数Data d4(2024, 12, 15); //给三个参数return 0;
}
且判断了年月日的合理性,非法的年月日会直接结束程序:
打印函数
void Ptint()
{cout << _year << "年" << _month << "月" << _day << "日" << endl;
}
测试代码:
拷贝构造函数
Data(const Data& d)
{_year = d._year;_month = d._month;_day = d._day;
}
拷贝构造函数也是类的默认成员函数,会在传参或者赋值时自动调用
防止无穷递归,所以参数部分使用引用接收,加上 const 是为了防止改变自身年月日
代码演示:
重载赋值运算符=
Data& operator=(const Data& d)
{if (this != &d){_year = d._year;_month = d._month;_day = d._day;}return *this;
}
返回值为 Data& 是为了适用于多次赋值的情况:
Data d1(2024, 12, 15);
Data d2;
Data d3;d3 = d2 = d1;
否则将返回值改为 void 的话就会赋值失败
参数中加上引用是为了避免浅拷贝,且用 const 修饰,是为了避免更改自身的值
if 语句判断是为了避免自己给自己赋值的情况,可以自己给自己赋值,但是没有必要
测试代码:
重载小于运算符<
bool operator<(const Data& 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 operator==(const Data& d)
{return _year == d._year &&_month == d._month &&_day == d._day;
}
全部都相等就会返回 true ,只要有一个不相等就会返回 false
调用函数:
d1 == d2
以上的代码可以转换为:
d1.operator==(d2)
所以函数中有一个隐藏的 this 指针就是 d1,参数中的 d 就是 d2
测试代码:
全等时:
不等时:
重载小于等于运算符<=
bool operator<=(const Data& d)
{return (*this < d) || (*this == d);
}
直接复用上面的小于运算符和全等于运算符即可
这里就不过多测试代码了,因为只要小于运算符和全等于运算符写对了,直接复用就是对的
重载大于运算符>
bool operator>(const Data& d)
{return !(*this <= d);
}
小于等于运算符取反后就是大于的逻辑
重载大于等于运算符>=
bool operator>=(const Data& d)
{return !(*this < d);
}
小于运算符取反后就是大于等于的逻辑
重载不等于运算符!=
bool operator!=(const Data& d)
{return !(*this == d);
}
全等于运算符取反后就是不等于的逻辑
重载加等运算符+=
Data& operator+=(int day)
{if (day < 0){return *this -= (-day);}_day += day;while (_day > GetMonthDay(_year, _month)){_day -= GetMonthDay(_year, _month);_month++;if (_month == 13){_month = 1;_year++;}}return *this;
}
先将要加的天数都加到当前的天数上
再利用 while 循环判断,只要当前天数大于了当月正确的天数,就要产生进位,往月份上进位
在 while 循环中要注意判断,当月份等于 13 是,说明就到了来年的 1 月,要赋值成 1
并且对年份自增 1,最后再把 *this ,就是加好天数后的对象返回即可
测试代码:
重载加法运算符+
Data operator+(int day)
{Data tmp(*this);tmp.operator+=(day);return tmp;
}
加等运算符是会改变自己,而加法运算符不会改变自己,所以要创建一个临时对象
然后直接复用加等运算符即可
需要注意的是,tmp 是临时对象,出了作用域就销毁了,所以不能引用返回
测试代码:
重载减等运算符-=
Data& 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;
}
先用当前日期的天数减去要自减的天数,如果减之后的天数为负数,就要向前借位
先对对象的月份递减1,并且判断当月份递减到 0 时,就说明递减到了昨年的 12 月
再把年份递减 1 ,最后把当前月份的天数加到日期的天数上,直到日期大于 0 时就成功减去了天数
因为 this 指针所指向的对象,出了作用域还在,所以可以使用传引用返回
测试代码:
重载减法运算符-(日期-天数)
Data operator-(int day)
{Data tmp(*this);tmp.operator-=(day);return tmp;
}
和重载加法运算符一样,直接复用减等运算符即可
测试代码:
重载前置++和后置++运算符的规定
重载 前置++ 和 后置++ 都是 operator++ 这个函数名
那么为了区分他们,在 后置++ 时,就会在函数参数中加一个整型参数
这个整型参数传不传参都可以,本质只是占位,为了区分 前置++ 而已
重载前置++运算符
Data& operator++()
{*this += 1;return *this;
}
测试代码:
重载后置++运算符
Data operator++(int)
{Data tmp(*this);*this += 1;return tmp;
}
测试代码:
重载前置--运算符
Data& operator--()
{*this -= 1;return *this;
}
重载后置--运算符
Data operator--(int)
{Data tmp(*this);*this -= 1;return tmp;
}
重载减法运算符-(日期-日期)
int operator-(const Data& d)
{Data maxData = *this;Data minData = d;int flag = 1;if (maxData < minData){maxData = d;minData = *this;flag = -1;}int n = 0;while (minData < maxData){n++;minData++;}return n * flag;
}
日期减日期有三种情况:
1. this 指针指向的日期大于 d 日期
2. this 指针指向的日期小于 d 日期
3. 两个日期相等
代码逻辑是:
将大的日期赋值给 maxData ,将小的日期赋值给 minData,如果赋值错误就矫正即可
重要的是 flag 变量,如果赋值没有错误的话,大日期减去小日期,结果是正数,否则就是负数,所以使用 flag 变量控制正负
最后再让 minData 递增,递增到和 maxData 相同时,n 的值就是相差的天数,并且要乘以 flag 来确定正负
测试代码:
为正数时:
为负数时: