【C++】类和对象--日期类的实现

目录

前言

判断日期是否合法

日期+=天数

日期+天数

日期-天数

日期-=天数

日期-日期(返回天数)

前置++ /  后置++

前置--  /  后置--

流插入<<重载

流提取>>重载

补充

源码


前言

我们前面学习了类和对象的6大默认函数,以及一些相关的知识点,现在我们来实现一下日期类,巩固一下成果。

判断日期是否合法

日期类的话,肯定是年月日这三个嘛,我们输入的时候,可能存在乱输入的情况

这样是不是不可以啊?

这里的话我们加一个判断,天数少于当前月份的天数,月份小于13大于0,是不是就可以啦

这里判断一下是不是闰年,四年一闰百年不闰

日期+=天数

我们c语言有一个点,+=就是当前的加上现在的再赋值给当前的,也就是说原来的这个值会被改变。a+=b 相当于a = a+b.

我们这里只需要判断是不是一年的最后一天,是的话单独处理一下。

日期+天数

这里其实可以重载一下+=的函数,我后面++再写重载吧。

+和+=的区别就是,+不改变原来的对象,+=改变原来的对象。那我们应该怎么样才能不改变对象呢?

这里的话我们可以用一个临时对象来赋值,是不是就可以啦

这样的话返回b1,原来的值就不会改变。

日期-天数

这里的话和+是一样的,只是符号不一样,然后需要判断是不是第一个月,要不要年份-1.

 但是这里有一个问题啊,如果我们输入的是一个负数的话,它还可以吗

是不是寄了啊?

这种情况,我们可以思考一下,- - 是不是就是+啊?那我们写一条判断语句,让它- - 的时候就调用+的函数,是不是就可以啊?

我们对前面的+函数也做一下处理

现在我们看一下负数的情况

这里的话刚好我加减都是51,所以两个都是一样的值。

日期-=天数

-=的话,和+=是一样的,也不用创建临时对象。

只是符号不一样,然后需要判断是不是第一个月,要不要年份-1.

如果天数减完是正数,就直接返回,不用循环判断了。

日期-日期(返回天数)

判断两个年月日之间差多少天

这里的话,我们可以做一个,先判断两个年月日之间哪个大,然后小的慢慢++,每次++都有一个变量+1,当++到和大的那个年月日相等时,我们创建的那个变量的值,就是相差的天数。

第一个大,差值就是正数,第二个大,第一个减第二个就是负数。

前置++ /  后置++ / 前置--  /  后置--

++就是+1,--就是-1

前置++时先++后使用,后置++时先使用后++

前置--时先--后使用,后置--时先使用后--

这里的+=和-=都是我们的赋值运算符重载,调用了前面的+=和-=函数。

流插入<<重载

我们前面的输出是不是这样写啊,cout<<数据成员<<endl;

如果我们自己写的话,能不能写出来呢

cout是std标准命名空间里面的函数,它能够自动识别要输出类型,同时有一个返回值。

我们先有样学样,看看行不行,out引用cout(cout是ostream库的)

为什么呢?我们前几篇有写过,对于函数重载来说,两个参数的话,第一个参数是左操作数,第二个参数是右操作数。
但是对于类成员函数来说,第一个参数是不是隐藏的this指针啊,它指向我们调用该函数的对象,所以这里第一个参数是Date对象的地址。

那就要反过来写

但是这样很别扭啊,有没有什么办法呢

我们可以写成全局函数试试

全局函数的话,就要两个参数了,一个是打印,一个是要打印的对象

这里有一个问题,我们要访问的成员是私有的啊,解决这个办法的话,要么是写到类里面去,要么就是我们现在要写的友元了。

这样的话,我们就可以像之前一样输出了。

流提取>>重载

流提取的话和我们的流插入是一样的,只是命名空间不同,istream,它两相同的命名空间是iostream。

补充

C++中通过类可以将数据 以及 操作数据的方法进行完美结合,通过访问权限可以控制那些方法在 类外可以被调用,即封装,在使用时就像使用自己的成员一样,更符合人类对一件事物的认知。 而且每个方法不需要传递Stack*的参数了,编译器编译之后该参数会自动还原,即C++中 Stack * 参数是编译器维护的,C语言中需用用户自己维护。

还有我们之前学的类的定义

一般建议将函数规模较小(即函数不是很长,具体没有准确的说法,取决于编译器内部实现)、不是递归、且频繁调用的函数实现成内联函数。
所以说,类里面的成员函数如果规模较小,适合做内联函数的,直接定义在类里面。 

同时内联函数只是对编译器的一个建议,如果规模较大的函数就算我们实现成内联函数编译器也不一定按照内联函数处理。
那在类里面也是这样,就算我们把全部的类成员函数都直接定义在类里面,也不一定会全部当做内联函数处理,编译器也还是会看它具体适不适合做内联。

然后就是大家可以保持一种批判的思维 ,我写的东西是会有一些错误的地方的,只是我现在还没发现,有一些书籍上的知识点也不一定对,俗话说嘛,既信书不如无书。

源码

#include<iostream>
using namespace std;
class Date
{
public:
	friend ostream& operator<<(ostream& out, const Date& d);
	friend istream& operator>>(istream& in,  Date& d);//输入不是固定,所以不能const
	// 获取某年某月的天数
	int GetMonthDay(int year, int month)
	{
		static int days[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30,
	   31 };
		int day = days[month];
		if (month == 2
			&& ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
		{
			day += 1;
		}
		return day;
	}
	// 全缺省的构造函数
	Date(int year = 1900, int month = 1, int day = 1)
	{
		cout << "Date" << endl;
		_year = year;
		_month = month;
		_day = day;
	}
	// 拷贝构造函数
   // d2(d1)
	Date(const Date& d)
	{
		cout << "Date& d" << endl;
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
	// 赋值运算符重载
   // d2 = d3 -> d2.operator=(&d2, d3)
	Date& operator=(const Date& d)
	{
		cout << "Date& operator=" << endl;
		if (this != &d)
		{
			_year = d._year;
			_month = d._month;
			_day = d._day;
		}
		return *this; //this出了作用域就修改了,加*是此时的地址指向的空间
	}
	// 析构函数
	~Date()
	{
		cout << "~Date" << endl;
	}
	// 日期+=天数
	Date& operator+=(int day)
	{
		if (day < 0)//对于负数进行处理
		{
			*this -= -day;
			return *this;
		}
		//cout << "Date& operator+=" << endl;
		_day += day;
		int getmonth = GetMonthDay(_year, _month);
		while (_day > getmonth)
		{
				if (_month == 12)
				{
					//cout << "Date& operator+=" << endl;
					_day -= getmonth; //天数减掉那个月的天数
					_month = 1;
					_year ++;
					getmonth = GetMonthDay(_year, _month); //更新月份天数
				}
				else
				{
					//cout << "Date& operator+=" << endl;
					_month++;
					_day -= getmonth; //天数减掉那个月的天数
					getmonth = GetMonthDay(_year, _month); //更新月份天数
				}
		}
		return *this;
	}
	// 日期+天数
	Date operator+(int day)
	{
		if (day < 0)//对于负数进行处理
		{
			Date b1(*this);
			*this - -day;
			return b1;
		}
		Date b1;
		b1._month = _month;
		b1._year = _year;
		b1._day = _day + day;
		int getmonth = GetMonthDay(b1._year, b1._month);
		while (b1._day > getmonth)
		{
			if (b1._month == 12)
			{
				//cout << "Date& operator+=" << endl;
				b1._day -= getmonth; //天数减掉那个月的天数
				b1._month = 1;
				b1._year++;
				getmonth = GetMonthDay(b1._year, b1._month); //更新月份天数
			}
			else
			{
				//cout << "Date& operator+=" << endl;
				b1._month++;
				b1._day -= getmonth; //天数减掉那个月的天数
				getmonth = GetMonthDay(b1._year, b1._month); //更新月份天数
			}
		}
		return b1;
	}
	// 日期-天数
	Date operator-(int day)
	{
		if (day < 0)//对于负数进行处理
		{
			Date b1(*this);
			*this + -day;
			return b1;
		}
		Date b1;
		b1._month = _month;
		b1._year = _year;
		b1._day = _day - day;
		int getmonth = GetMonthDay(b1._year, b1._month);
		while (b1._day <= 0)
		{
			if (b1._month == 1)
			{ 
				b1._month = 12;
				b1._year--;
				getmonth = GetMonthDay(b1._year, b1._month); //更新月份天数
				b1._day += getmonth; //天数 那个月的天数
			}
			else
			{
				//cout << "Date& operator+=" << endl;
				b1._month--;//<=0,先减月份
				getmonth = GetMonthDay(b1._year, b1._month); //更新月份天数
				b1._day += getmonth; //天数 那个月的天数
			}
		}
		return b1;
	}
	// 日期-=天数
	Date& operator-=(int day)
	{
		if (day < 0)//对于负数进行处理
		{
			*this += -day;
			return *this;
		}
		//cout << "Date& operator+=" << endl;
		_day -= day;
		int getmonth = GetMonthDay(_year, _month);
		while (_day <= 0)
		{
			if (_month == 1)
			{
				_month = 12;
				_year--;
				getmonth = GetMonthDay(_year, _month); //更新月份天数
				_day += getmonth; //天数 那个月的天数
			}
			else
			{
				//cout << "Date& operator+=" << endl;
				_month--;//<=0,先减月份
				getmonth = GetMonthDay(_year, _month); //更新月份天数
				_day += getmonth; //天数 那个月的天数
			}
		}
		return *this;
	}
	// 前置++
	Date& operator++()
	{
		*this += 1;
		return *this;
	}
	// 后置++
	Date operator++(int)
	{
		Date b1(*this);
		*this += 1;
		return b1;
	}
	// 后置-
	Date operator--(int)
	{
		Date b1(*this);
		*this -= 1;
		return b1;
	}
	// 前置-
	Date& operator--()
	{
		*this -= 1;
		return *this;
	}
	// >运算符重载
	bool operator < (const Date& 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;
		return false;
	}
	// <=运算符重载
	bool operator <= (const Date& d)
	{
		return *this == d || *this < d;
	}
	bool operator>(const Date& d)
	{
		return !(*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);
	}
	// <运算符重载
	// !=运算符重载
	bool operator != (const Date& d)
	{
		return !(*this == d);
	}
	// 日期-日期  返回天数
	int operator-(const Date& d)
	{
		Date max = *this;
		Date min = d;
		int flag = 1;
		if (*this < d)
		{
			max = d;
			min = *this;
			flag = -1;
		}
		int n = 0;
		while (min != max)
		{
			++min;
			++n;
		}
		return n * flag;
	}
	void Print()
			{
				//cout << _year << "/" << _month << "/" << _day << endl;
				cout << _year << "年" << _month << "月" << _day << "日" << endl;
			}
private:
	int _year;
	int _month;
	int _day;
};
//<<
ostream& operator<<(ostream& out, const Date& d)
{
	out << d._year << "-" << d._month << "-" << d._day << endl;
	return out;
}
istream& operator>>(istream& in, Date& d)
{
	in >> d._year >> d._month >> d._day;
	return in;
}
int main()
{
	Date a1(2024, 12, 1);
	a1 += -51;
	a1.Print();
	Date c1 (a1);
	a1 -= -51;
	c1.Print();
	a1.Print();
	return 0;
}

日期类的实现就到这里啦,可能解析没讲两句,因为基本每个实现都差不多是一样的,大家看到错的可以跟我说,加油~

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值