日期类的实现

一.日期类头文件的定义

#include <iostream>
using namespace std;

class Date
{
public:
	//全缺省构造函数
	Date(int year,int month,int day):
		_year(year),
		_month(month),
		_day(day)
	{}

	//析构函数
	~Date()
	{
		_year = 0;
		_month = 0;
		_day = 0;
	}

	//拷贝构造
	Date(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}

	//赋值运算符重载
	Date& operator=(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;

		return *this;
	}

	int GetMonthDay(int year,int month)
	{
		static int day[13] = {-1,31,28,31,30,31,30,31,31,30,31,30,31};

		if (_month == 2 &&
			(((_year % 4 == 0) && (_year % 100 != 0)) || (_year % 400 == 0)))
		{
			return 29;
		}
		else
		{
			return day[_month];
		}
	}

	// 日期+=天数
	Date& operator+=(int day);

	// 日期+天数
	Date operator+(int day);

	// 日期-天数
	Date operator-(int day);

	// 日期-=天数
	Date& operator-=(int day);

	// 前置++
	Date& operator++();

	// 后置++
	Date operator++(int);

	// 后置--
	Date operator--(int);

	// 前置--
	Date& operator--();

    //>>运算符重载
    friend istream& operator>>(istream& input, Date& d);

    //<<运算符重载
    friend ostream& operator<<(ostream& output, const Date& d);

	// >运算符重载
	friend bool operator>(const Date& d1,const Date& d2);

	// ==运算符重载
	friend bool operator==(const Date& d1, const Date& d2);

	// >=运算符重载
	friend bool operator >= (const Date& d1, const Date& d2);

	// <运算符重载
	friend bool operator < (const Date& d1, const Date& d2);

	// <=运算符重载
	friend bool operator <= (const Date& d1, const Date& d2);

	// !=运算符重载
	friend bool operator != (const Date& d1, const Date& d2);

	// 日期-日期 返回天数
	friend int operator-(const Date& d1, const Date& d2);

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

二.日期类成员函数的实现

2.1GetMonthDay()

当我们在实现日期的加减时,要频繁的计算当前月的天数,而且根据闰年平年的变化,2月的天数也会跟着变化。所以我们可以实现一个函数,专门用来计算某年某月的天数。

int GetMonthDay(int year,int month)
{
	static int day[13] = {-1,31,28,31,30,31,30,31,31,30,31,30,31};

	if (_month == 2 &&
		(((_year % 4 == 0) && (_year % 100 != 0)) || (_year % 400 == 0)))
	{
		return 29;
	}
	else
	{
		return day[_month];
	}
}

因为该函数需要频繁地使用,所以直接将其定义在类内,称为内联函数,可以提升效率。而函数内部我们可以用一个数组将每个月存储起来,因为这个数组在程序运行过程中也需要多次使用,所以我们可以将其定义为static,避免每次都要创建这个数组。

2.2流提取和流插入运算符重载

//>>运算符重载
istream& operator>>(istream& input, Date& d)
{
	cout << "请依次输入年月日->:";
	while (1)
	{
		input >> d._year >> d._month >> d._day;

		//判断输入的年月日是否合法
		if (d._month > 12 || d._month <1 || d._day>d.GetMonthDay() || d._day < 1)
		{
			cout << "非法日期,请重新输插入->:";
		}
		else
		{
			break;
		}
	}

	return input;
}
//<<运算符重载
ostream& operator<<(ostream& output, const Date& d)
{
	cout << d._year << "/" << d._month << "/" << d._day << endl;

	return output;
}

对于输入来说,我们要在用户输入之后对日期进行检查,如果日期非法,我们要提醒用户该日期是非法的,并重新输入。

2.3比较运算符重载

大于号的实现,我们可以将ture的条件挑出来,其他的都是false,到最后返回即可。

// >运算符重载
bool operator>(const Date& d1, const Date& d2)
{
	if (d1._year > d2._year)
	{
		return true;
	}
	else if (d1._year == d2._year)
	{
		if (d1._month > d2._month)
		{
			return true;
		}
		else if (d1._month == d2._month)
		{
			if (d1._day > d2._day)
			{
				return true;
			}
		}
	}
	return false;
}
// ==运算符重载
bool operator==(const Date& d1, const Date& d2)
{
	if (d1._year == d2._year
		&& d1._month == d2._month
		&& d1._day == d2._day)
	{
		return true;
	}
	return false;
}

 剩下的操作符都可以复用大于和等于来实现:

// >=运算符重载
bool operator >= (const Date& d1, const Date& d2)
{
	return !(d1 < d2);
}

// <运算符重载
bool operator < (const Date& d1, const Date& d2)
{
	return !(d1 > d2 || d1 == d2);
}

// <=运算符重载
bool operator <= (const Date& d1, const Date& d2)
{
	return !(d1 > d2);
}

// !=运算符重载
bool operator != (const Date& d1, const Date& d2)
{
	return !(d1 == d2);
}

2.4日期加减一个整数

// 日期+天数
Date Date::operator+(int day)
{
	Date tmp = *this;

	tmp._day += day;
	while (tmp._day > tmp.GetMonthDay())
	{
		tmp._day -= tmp.GetMonthDay();
		tmp._month += 1;
		if (tmp._month > 12)
		{
			tmp._year += 1;
			tmp._month = 1;
		}
	}
	return tmp;
}

// 日期-天数
Date Date::operator-(int day)
{
	Date tmp = *this;

	tmp._day -= day;
	while (tmp._day < 1)
	{
		tmp._month -= 1;
		if (tmp._month < 1)
		{
			tmp._year -= 1;
			tmp._month = 12;
		}
		tmp._day += tmp.GetMonthDay();
	}
	return tmp;
}

我们可以先实现+、-一个整数,因为加减运算符不会改变原操作数,所以在实现时不要改变this,否则结果会出错。

然后我们可以借助+、-来实现+=、-=。 

// 日期+=天数
Date& Date::operator+=(int day)
{
	*this = *this + day;
	return *this;
}

// 日期-=天数
Date& Date::operator-=(int day)
{
	*this = *this - day;

	return *this;
}

这两个操作符在使用时会改变原操作数,所以我们可以复用加减来快速实现+=、-=的实现。 

2.5++、--运算符重载

自增自减运算符也可以复用+=以及-=来实现,只不过要区分是前置还是后置,后置的函数会携带一个int形参,该形参只起到区分作用。

前置++/--,返回++/--之后的值

后置++/--,返回++/--之前的值

/ 前置++
Date& Date::operator++()
{
	return *this += 1;
}

// 后置++
Date Date::operator++(int)
{
	Date tmp = *this;
	*this += 1;
	return tmp;
}

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

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

2.6日期减日期

日期相减得到天数,我们可以假设法找到日期大的和日期小的,两个日期直接相减不方便计算,我们可以让小日期++,然后记录加的次数,知道两者相等,加的次数就是之间相差的天数。正数则表示d1<d2,表示将来。负数则表示d1>d2表示过去。

// 日期-日期 返回天数
int operator-(const Date& d1, const Date& d2)
{
	int day = 0;

	Date max = d2;
	Date min = d1;
	int flag = 1;
	if (max < min)
	{
		max = d1;
		min = d2;
		flag = -1;
	}
	while (max > min)
	{
		min += 1;
		day += 1;
	}
	return flag*day;
}

三.对函数进行调整

这个日期类涉及到了多个成员函数,而有的成员函数并不会修改其参数,所以我们可以将其定义为const成员函数。

 我们在调用构造函数的时候也有可能传非法日期,所以我们可以实现一个日期检查函数,再构造函数中进行检查:

bool Check()
{
	if (_month > 12 || _month <1 || _day >GetMonthDay() || _day < 1)
	{
		return false;
	}
	return true;
}

我们也可以采取更暴力的手段,直接在构造函数中进行assert断言检查,如果断言失败,程序直接终止:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值