日期类的实现_r6-3 日期类的设计与实现使用重载运算符(++,+=,<<等)实现日期类的操作。功能包括

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事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行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

  • 15
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值