网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
用复用的定义
一行搞定,< 和 == 的重载我们已经写过了,在这里我们可以直接使用他们,会方便好多,不需要我们再次将冗余的代码写一次并再次判断逻辑。
bool Date::operator <= (const Date& d)
{
return *this < d || *this == d;
}
1.4 ‘>’重载
声明
// >运算符重载
bool operator>(const Date& d);
定义
直接用复用我们已经写过的 <= :
bool Date::operator>(const Date& d)
{
return !(*this <= d);
}
1.5 ‘>=’重载
声明
// >=运算符重载
inline bool operator >= (const Date& d);
定义
直接复用 > 和 == :
bool Date::operator >= (const Date& d)
{
return *this > d || *this == d;
}
或者复用 < :
bool Date::operator >= (const Date& d)
{
return !(*this < d);
}
1.6 ‘!=’重载
声明
// !=运算符重载
bool operator != (const Date& d);
定义
复用 == ,取反即可:
bool Date::operator != (const Date& d)
{
return !(*this == d);
}
2. 赋值 ‘=’重载
声明
// 赋值运算符重载
// d2 = d3 -> d2.operator=(&d2, d3)
Date& operator=(const Date& d);
定义
返回的就是Date类型,就好比有两个整型变量: a=b ,返回的类型也是整型
为什么要加引用呢?
a.this指针出了函数作用域会销毁,但是this所指向的内容是不会销毁的,因此我们可以考虑使用引用返回
b. 并且如果不用引用返回,同类型的对象传值传参会调用拷贝构造,减少开销,也推荐使用引用返回
Date& Date::operator=(const Date& d)
{
if (*this != d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
return *this;
}
3. 对日期天数进行计算
对日期进行计算:
比如加上天数减去天数,会涉及到月份或年的增加或减少问题。这里就需要判断天数是否超过当前对应月份天数的限制,月份是否超过12等等。并且对于特殊的2月,我们还需区分闰年和平年。
确定月份天数
声明
最后返回的是天数
int GetMonthDay(int year, int month);
定义
//Leapyear(year) 是bool类型,判断是否是闰年
int Date::GetMonthDay(int year, int month)
{
在这里对年和月份进行判定
assert(year >= 0 && month>0 && month<13);
static int MDay[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
if (month == 2 && Leapyear(year))
{
return 29;
}
else
{
return MDay[month];
}
}
这里要注意为什么在数组前加上 static ,不加也是可以的,但是每次创建时调用此函数,都会开辟出新数组,static 可以保持此数组只初始化一次,使用时再次调用即可,可降低开销,提高效率。
判断是否是闰年
定义
我们直接将此函数在类中定义,将默认他是内联函数:
bool Leapyear(int year)
{
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
{
return true;
}
else
{
return false;
}
}
3.1 日期加天数 ‘+’的重载
声明
// 日期+天数
Date operator+(int day);
定义
这里首先要用到拷贝构造,创建一个临时的日期类,对临时的进行更改,最后返回,就比如 a+3后,a 是不改变的。a = a+3,a才会改变。这里的运算相当于a+3
要考虑天数过大时,边界问题,天数有边界,月份有边界,超过月份的天数限制,月份+1,月份==13时,年+1
按照此逻辑进项实现:
Date Date::operator+(int day)
{
Date ret(*this);
ret._day += day;
while (ret._day>GetMonthDay(ret._year,ret._month))
{
ret._day -= GetMonthDay(ret._year, ret._month);
ret._month++;
if (ret._month == 13)
{
ret._year++;
ret._month = 1;
}
}
return ret;
}
小拓展
当一个对象取初始化另一个不存在的对象时,调用的是构造拷贝
只有两个存在的对象使用=时,才是赋值
3.2 日期加天数 ‘+=’的重载
相当于 a=a+b ,a本身会改变
声明
// 日期+=天数
Date& operator+=(int day);
定义
和+的逻辑相同,只不过是直接修改 this 指向的内容,注意这里的返回值与 + 不同,+ 返回的是临时变量,用传值,而这里this会销毁, *this 不会销毁,直接返回 *this即可,返回它本身用引用返回。
判断day为负的情况,复用 -=
+=负值等价于-=正值:
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 == 13)
{
_year++;
_month = 1;
}
}
return *this;
}
3.3 +和+=相互复用定义比较
复用+定义+=
简便很多
Date& Date::operator+=(int day)
{
*this = *this + day;
return *this;
}
复用+=定义 +
+= 不复用+来实现,那么+就可以复用 +=来实现
Date Date::operator+(int day)
{
Date ret(*this);
ret += day;
return ret;
}
到底谁复用谁效果更好呢?
分别调用两种方式的+和+=
由拷贝构造的次数来看,+ 复用 += 效率会更高一些。
由此推出:- 复用 -= 效率会更高。
3.4 日期减天数‘-=’的重载
声明
// 日期-=天数
Date& operator-=(int day);
定义
这里特别要注意的是当月份为0,时,重置月份,更新天数的时候,用更新后的月份来计算。
最后返回*this,不会销毁,用引用返回。
判断day为负的情况,复用 +=
-=负值等价于+=正值:****:
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;
}
3.5 日期减天数‘-’的重载
声明
// 日期-天数
Date operator-(int day);
用复用 -= 定义 -
Date Date::operator-(int day)
{
Date ret(*this);
ret -= day;
return ret;
}
4.日期 ++ 和 ++
4.1 ++
++运算符重载分为前置++和后置++,他们的函数形式如下:
// 前置++
Date& operator++();
// 后置++
Date operator++(int);
函数名相同,为了区分开来,语法规定:
没有参数的为前置++
有参数的为后置++
直接在类中定义
前置++,直接改变*this的内容
后置++,*this不变,返回的是此函数中构建好的临时变量,临时变量进行运算操作之后返回
// 前置++
Date& operator++()
{
*this += 1;
return *this;
}
// 后置++
Date operator++(int)
{
Date ret(*this);
ret += 1;
return ret;
}
4.2 –
和++同理,直接在类中定义:
// 后置--
Date operator--(int)
{
Date ret(*this);
ret -= 1;
return ret;
}
// 前置--
Date& operator--()
{
*this -= 1;
return *this;
}
5. 求日期差,返回天数
两个日期不相等时,求他们之间相差多少天
声明
// 日期-日期 返回天数
int operator-(const Date& d);
思路
第一思路:
年之间比较求差,月之间比较求差,天之间比较球差,最后判断对应天数,累加即可。
缺点:分别判断,分别计算,过程太繁琐
第二思路:
首先判断谁大谁小,让小的开始累加,直到和大的相等为止,只需要计加了多少天即可。
定义
这里flag来确定正负,如果现在和未来比,天数是正的,加上天数即可和大的相等
如果是现在和过去比,天数是负的,现在+天数等于过去的时间
int Date::operator-(const Date& d)
{
int flag = 1;
Date max = *this;
Date min = d;
if (*this<d)
{
min = *this;
max = d;
flag = -1;
}
//让小的累加至大的
//累加的天数n为差值
int n = 0;
while (min != max)
{
n++;
min++;
}
return n*flag;
}
Date.h
#define _CRT_SECURE_NO_WARNINGS
#pragma once
#include <cassert>
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
class Date
{
public:
// 获取某年某月的天数
bool Leapyear(int year)
{
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
{
return true;
}
else
{
return false;
}
}
int GetMonthDay(int year, int month);
// 全缺省的构造函数
Date(int year = 1900, int month = 1, int day = 1)
{
if (year < 1900 ||
month < 1 || month > 12 ||
day < 1 || day > GetMonthDay(year, month))
{
cout << "非法日期" << endl;
}
_year = year;
_month = month;
_day = day;
}
拷贝构造函数
// d2(d1)
Date(const Date& d)
{
cout << "构造拷贝" << endl;
_year = d._year;
_month = d._month;
_day = d._day;
}
// 赋值运算符重载
// d2 = d3 -> d2.operator=(&d2, d3)
Date& operator=(const Date& d);
// 析构函数
~Date()
{
}
// 日期+=天数
Date& operator+=(int day);
// 日期+天数
Date operator+(int day);
// 日期-天数
Date operator-(int day);
// 日期-=天数
Date& operator-=(int day);
// 前置++
Date& operator++()
{
*this += 1;
return *this;
}
// 后置++
Date operator++(int)
{
Date ret(*this);
ret += 1;
return ret;
}
// 后置--
Date operator--(int)
{
Date ret(*this);
ret -= 1;
return ret;
}
// 前置--
Date& operator--()
{
*this -= 1;
return *this;
}
// >运算符重载
bool operator>(const Date& d);
// ==运算符重载
bool operator==(const Date& d);
// >=运算符重载
inline bool operator >= (const Date& d);
// <运算符重载
bool operator < (const Date& d);
// <=运算符重载
bool operator <= (const Date& d);
// !=运算符重载
bool operator != (const Date& d);
// 日期-日期 返回天数
int operator-(const Date& d);
void SetDate(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
void Print()
{
![img](https://img-blog.csdnimg.cn/img_convert/7dbe8d922b7b4c1a8058e88f2a14e3cb.png)
![img](https://img-blog.csdnimg.cn/img_convert/4845173d4f637cf62109cf23cda054f3.png)
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化的资料的朋友,可以添加戳这里获取](https://bbs.csdn.net/topics/618668825)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
is -= 1;
return *this;
}
// >运算符重载
bool operator>(const Date& d);
// ==运算符重载
bool operator==(const Date& d);
// >=运算符重载
inline bool operator >= (const Date& d);
// <运算符重载
bool operator < (const Date& d);
// <=运算符重载
bool operator <= (const Date& d);
// !=运算符重载
bool operator != (const Date& d);
// 日期-日期 返回天数
int operator-(const Date& d);
void SetDate(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
void Print()
{
[外链图片转存中...(img-5lV0KFK7-1715809940977)]
[外链图片转存中...(img-5kAq3cvk-1715809940977)]
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化的资料的朋友,可以添加戳这里获取](https://bbs.csdn.net/topics/618668825)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**