实现日期类

前言:

        本篇我们要实现一个日期类,其实非常困难,因为要对日期实现加加减减,也就是要对前面的知识做出一个巩固。

头文件:

        因为要判断闰年,所以我们要去创建一个数组。也就是创建一个返回每月日期的函数。因为闰年要单独判断,所以

        这里有一个知识点,就是直接声明在类中的函数,都是内联函数。

//直接定义在类里面,默认是inline(内联)
//频繁调用
int getMonthDay(int year, int month)
{
	assert(month > 0 && month < 13);

	//默认平年
	static int monthDayArray[13] = { -1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
	//判断闰年,先判断2月再判断闰年
	if (month == 2 && year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
	{
		return 29;
	}
	else 
	{
		return monthDayArray[month];
	}

	return monthDayArray[month];
}

日期相加:

        日期类相加是有意义的,我们相当于对未来几天的计算。

        我们完成日期类,先写+=,之后完善+可以复用+=。

        复用+=比较好,因为复用+的话会先调用拷贝构造,之后返回的时候再调用一次拷贝构造。

Date& Date::operator+=(int day)
{
	if (day < 0)
	{
		return *this -= -day;
	}

	_day += day;
	//这里是while循环
	while (_day > getMonthDay(_year, _month))
	{
		_day -= getMonthDay(_year, _month);
		_month++;
		if (_month == 13)
		{
			_year++;
			_month = 1;
		}
	}

	return *this;
}

Date Date::operator+(int day) const
{
	Date tmp = *this;//拷贝构造
	//再写一遍就会很冗余,所以直接调用+=
	tmp += day;

	return tmp;
	//此时不能使用引用返回,因为会销毁tmp
}

日期相减: 

        这也是有意义的。

        日期类相减我们需要注意的事项: 函数重载和运算符重载没有关系。

        多个同一运算符可以构成函数重载。

日期++:

        此时如果我们要实现前置++和后置++的运算符重载,为了区分,后置++需要强制加上int形参。

//++d1
Date& operator++();

//d1++
//为了区分,构成重载
//强行给后置++ 增加了一个int形参
Date& operator++(int);

打印日期: 

        自动识别类型本质是因为流插入重载构成函数重载。

        因为可以直接打印内置类型,但是此时我们想直接打印引用类型,我们就需要自己去写。

        operator<< 想重载为成员函数,可以,但是用起来不符合正常逻辑,不建议这样使用,建议重载为全局函数。所以我们使其成为全局函数。

void operator<<(ostream& out, Date d)
{
	//out就是cout
	out << d._year << "年" << d._month << "月" << d._day << "日" << endl;
}

        但是此时私有的问题又出现了,我们可以利用友元……看图:

        本质就是实参顺序,但是此时:

cout << d1 << d2;

        会报错,所以该怎么办呢?因为流插入结合性是从左往右,所以要返回ostream&才行。

ostream& operator<<(ostream& out, Date d);

        这样就支持链式输出。 

传入const常量: 

        如果我们定义一个常量的日期类,如果直接调用里面的函数,会报错。

void Date::Print() const
{
	cout << _year << "-" << _month << "-" << _day << endl;
}

        因为权限可以缩小,所以对于比较的函数最好都加上const(也就是没有改变*this的函数)。

        +=不能加const,但是+可以,因为+=相当于修改了*this,但是+不会。

总结:

        没啥总结,就是有空再写一遍,这里给出全部代码:

Date.h头文件:

#pragma once
#include<iostream>
#include<assert.h>

using namespace std;

class Date
{
	//设置友元函数声明
	//流插入初始为全局函数
	friend ostream& operator<<(ostream& out, const Date d);
	//流提取
	friend istream& operator>>(istream& in, Date& d);
public:
	//缺省函数在定义的时候给
	Date(int year = 1900, int month = 1, int day = 1);
	void Print() const;

	//直接定义在类里面,默认是inline(内联)
	//频繁调用
	int getMonthDay(int year, int month)
	{
		assert(month > 0 && month < 13);

		//默认平年
		static int monthDayArray[13] = { -1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
		//判断闰年,先判断2月再判断闰年
		if (month == 2 && year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
		{
			return 29;
		}
		else 
		{
			return monthDayArray[month];
		}

		return monthDayArray[month];
	}

	//检查日期合法性
	bool CheckDate();

	bool operator<(const Date& d) const;
	bool operator<=(const Date& d) const;
	bool operator>(const Date& d) const;
	bool operator>=(const Date& d) const;
	bool operator!=(const Date& d) const;
	bool operator==(const Date& d) const;

	Date& operator+=(int day);
	Date operator+(int day) const;
	Date& operator-=(int day);

	// d1 - 100
	Date operator-(int day) const;

	// d1 - d2
	int operator-(const Date& d) const;

	//++d1 -> d1.operator++()
	Date& operator++();

	//d1++ -> d1.operator++(1)
	//为了区分,构成重载
	//强行给后置++ 增加了一个int形参
	Date operator++(int);

	Date& operator--();
	Date operator--(int);

	//流插入
	//不建议,因为Date* this 占据了第一个参数位置,使用 d << cout 不符合习惯
	//void operator<<(ostream& out);//必须传入引用

private:
	int _year;
	int _month;
	int _day;
};

//流插入初始为全局函数
ostream& operator<<(ostream& out, const Date d);
//流提取
istream& operator>>(istream& in, Date& d);

Date.cpp源文件:

#include"Date.h"

//检查日期合法性
bool Date::CheckDate()
{
	if (_month < 1 || _month > 12
		|| _day < 1 || _day > getMonthDay(_year, _month))
	{
		return false;
	}

	return true;
}

Date::Date(int year, int month, int day)
{
	_year = year;
	_month = month;
	_day = day;

	if (!CheckDate())
	{
		cout << "日期非法" << endl;
	}
}

void Date::Print() const
{
	cout << _year << "-" << _month << "-" << _day << endl;
}

bool Date::operator<(const Date& d) const
{
	if (_year < d._year) {
		return true;
	}
	else if (_year == d._year)
	{
		if (_month < d._month)
		{
			return true;
		}
		else if (_month == d._month)
		{
			return _day < d._day;
		}
	}

	return false;
}

bool Date::operator==(const Date& d) const
{
	return _year == d._year
		&& _month == d._month
		&& _day == d._day;
}

bool Date::operator<=(const Date& d) const
{
	return *this < d || *this == d;
}

bool Date::operator>(const Date& d) const
{
	return !(*this <= d);
}

bool Date::operator>=(const Date& d) const
{
	return !(*this < d);
}

bool Date::operator!=(const Date& d) const
{
	return !(*this == d);
}

Date& Date::operator+=(int day)
{
	if (day < 0)
	{
		return *this -= -day;
	}

	_day += day;
	//这里是while循环
	while (_day > getMonthDay(_year, _month))
	{
		_day -= getMonthDay(_year, _month);
		_month++;
		if (_month == 13)
		{
			_year++;
			_month = 1;
		}
	}

	return *this;
}

Date Date::operator+(int day) const
{
	Date tmp = *this;//拷贝构造
	//再写一遍就会很冗余,所以直接调用+=
	tmp += day;

	return tmp;
	//此时不能使用引用返回,因为会销毁tmp
}

//Date Date::operator+(int day)
//{
//
//	Date tmp = *this;//拷贝构造
//	tmp._day += day;
//	//这里是while循环
//	while (tmp._day > getMonthDay(tmp._year, tmp._month))
//	{
//		tmp._day -= getMonthDay(tmp._year, tmp._month);
//		tmp._month++;
//		if (tmp._month == 13)
//		{
//			tmp._year++;
//			tmp._month = 1;
//		}
//	}
//
//	return tmp;
//	//此时不能使用引用返回,因为会销毁tmp
//}
//
//Date& Date::operator+=(int day)
//{
//	 *this = *this + day;
//	return *this;
//}


Date& Date::operator-=(int day)
{
	if (day < 0)
	{
		return *this += -day;
	}

	_day -= day;
	while (_day <= 0)
	{
		//小于等于0都需要继续
		_month--;
		if (_month == 0)
		{
			_month = 12;
			_year--;
		}

		//借上个月的天数
		_day += getMonthDay(_year, _month);
	}
	return *this;
}

Date Date::operator-(int day) const
{
	Date tmp = *this;
	tmp -= day;
	return tmp;
}

//++d1 -> d1.operator++()
Date& Date::operator++()
{
	*this += 1;
	return *this;
}

//d1++ -> d1.operator++(1)
//为了区分,构成重载
//强行给后置++ 增加了一个int形参 (这个形参可加可不加)
Date Date::operator++(int)
{
	//先拷贝
	Date tmp(*this);
	*this += 1;
	return tmp;
}

Date& Date::operator--()
{
	*this -= 1;
	return *this;
}

Date Date::operator--(int)
{
	Date tmp = *this;
	*this -= 1;
	return tmp;
}

int Date::operator-(const Date& d) const
{
	//两个日期相减, 让小的加到大的为止
	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 Date::operator<<(ostream& out)
//{
//	//out就是cout
//	out << _year << "年" << _month << "月" << _day << "日" << endl;
//}

ostream& operator<<(ostream& out, const Date d)
{
	//out就是cout
	out << d._year << "年" << d._month << "月" << d._day << "日" << endl;
	return out;
}

//流提取
istream& operator>>(istream& in, Date& d) {
	cout << "请一次输入年月日:" << endl;
	in >> d._year >> d._month >> d._day;

	if (!d.CheckDate())
	{
		cout << "日期非法" << endl;
	}

	return in;
}

test.cpp源文件:

using namespace std;

#include"Date.h"

void TestDate1()
{
	Date d1(2024, 4, 14);
	Date d2 = d1 + 5000;
	d1.Print();
	d2.Print();
	d1 += 5000;
	d1.Print();
	cout << endl;

	Date d3(2024, 4, 14);
	Date d4 = d3 - 5000;
	d3.Print();
	d4.Print();
	d3 -= 5000;
	d3.Print();

	Date d5(2024, 4, 14);
	d5 += -5000;
	d5.Print();
}

void TestDate2()
{
	Date d1(2024, 4, 14);
	Date d2 = ++d1;
	d1.Print();
	d2.Print();

	Date d3 = d1++;
	d3.Print();
	d1.Print();
}

void TestDate3()
{
	Date d1(2024, 4, 25);
	Date d2(2034, 4, 25);
	int n = d1 - d2;
	cout << n << endl;
}

void TestDate4()
{
	Date d1(2024, 4, 25);
	Date d2(2034, 4, 25);
	//d1.operator<<(cout);
	//cout << d1;
	//d1 << cout;//要这样写
}

void TestDate5()
{
	Date d1(2024, 4, 25);
	Date d2(2034, 4, 25);
	cout << d1;
	cout << d1 << d2;
	cin >> d2;
	d2.Print();
}

void TestDate6()
{
	const Date d1(1024, 4, 27);
	//这里相当于权限放大
	d1.Print();
}

int main()
{
	//TestDate2();
	//TestDate3();
	//TestDate4();
	//TestDate5();
	TestDate6();
	return 0;
}

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值