【C++】实现日期类运算符重载

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_41035588/article/details/83247178

什么是日期类?

用C++来实现一个日期类Date,包括年(_year)、月(_month)、日(day),来实现对日期的自增(++),自减(–),加上特定天数(+days),减去指定天数(-days),输入输出的实现,以及通过输入两个特定的日期,来计算相隔的天数。其中会用到构造函数、拷贝构造函数、析构函数,以及多类运算符的重载。

日期类实现思路

在设计日期类过程中,有一个月份相对特殊,那就是二月。可以通过判断是否闰年来确定二月的天数,为了后面实现的方便与简洁,可以将12个月的天数存储于一个一维数组中。在运算符重载中,对this指针的迷惑可以查看 this指针的详解。重载中会巧妙运用引用&及const关键字,程序中会降低一些算法的复杂度,具体实现将在函数调用中详细介绍。

函数调用模块

①构造函数及非法日期判断(以1900-1-1日为下限)

// 全缺省参数构造函数
	Date(int year = 1997, int month = 11, int day = 4)
		:_year(year)
		, _month(month)
		, _day(day)
	{
		//检查合法
		if (year >= 0
			&& _month > 0 && _month < 13
			&& _day > 0 && _day <= GetMonthDay(year, month))
		{
			_year = year;
			_month = month;
			_day = day;
		}
		else
		{
			cout << "Date Invalid" << endl;
		}
	}

②拷贝构造函数(注意函数参数为const Date&类型)

//拷贝构造函数:Date d3(d1)或者 Date d3 = d1
	Date::Date(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}

③析构函数(可以在里面打印"~Date",什么都不做也可以,对于动态开辟内存,在析构函数中free)

~Date()
	{
		;
	}

④ 判断是否闰年(4年一闰,逢百年不闰,400年一闰与获取某年某月的指定天数(判断闰年后月份已经确定,可存储于数组中方便调用)

//获取当月天数
int Date::GetMonthDay(int year, int month)
{
	//方法一:十二个if、else语句
	//方法二:switch分支语句
	//此处方法三:
	 static const int days[13] = {0, 31,28, 31,30, 31,30, 31,31,30, 31,30, 31 };//润年二月多一天
	 //4年一润百年不润400年一润且此处至于二月有关
	 if ((month == 2)&&((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
	 {
		 return 29;

	 }
	 return days[month];
}

⑤赋值运算符 = 重载(分两种情况:1.自己给自己赋值,但是无意义,建议不使用 2.自己给别人赋值)

//赋值操作符重载
	Date&  Date::operator=(const Date& d)
	{
		if (this != &d)
		{
			_year = d._year;
			_month = d._month;
			_day = d._day;
		}
		return *this;
	}

⑥取地址操作符重载

//取地址操作符重载
	Date* operator&()
	{
		return this;
	}

⑦重载 + days(加上指定天数)的重载(当+days大于该月总天数时,用days减去该月天数,月份month+1,差值即为新月份的天数。若遇到年末,即month = 12时,年份year++,月份month置1,否则month++)

Date Date::operator+(int day)
{
	Date ret(*this);

	if (day<0)
		return ret - abs(day);
	ret._day += day;

	while (ret._day > GetMonthDay(ret._year, ret._month))
	{
		ret._day -= GetMonthDay(ret._year,ret._month);
		if (12 == ret._month)
		{
			ret._year++;
			_month = 1;

		}
		else
		{
			_month += 1;
		}
	}
	return ret;
}

Date& Date::operator+=(int day)
{
	if (day<0)
	{
		return *this - abs(day);
	}
	
	_day += day;
	while (_day > GetMonthDay(_year, _month))
	{
		_day -= GetMonthDay(_year, _month);
		if (12 == _month)
		{
			_year++;
			_month = 1;

		}
		else
		{
			_month += 1;
		}
	}
	return *this;
}

⑧重载 - days (减去指定天数)的重载(与+days类似,用该月天数-days,其差值若小于0,且在年初,则年份year–,置月份month=12,否则month–)

//(与+days类似,用该月天数-days,
//其差值若小于0,且在年初,则年份year--,置月份month=12,否则month--)
Date Date::operator-(int day)
{
	Date ret(*this);

	if (day < 0)
		return ret + abs(day);
	ret._day -= day;
	while (ret._day <= 0)
	{

		if (ret._month == 1)
		{
			ret._year--;
			ret._month = 12;
		}
		else
		{
			ret._month--;
		}
		ret._day += GetMonthDay(ret._year,ret._month);

	}
	return ret;
}
Date& Date::operator-=(int day)
{
	if (day < 0)
		return *this + abs(day);
	_day -= day;
	while (_day <= 0)
	{
		if (_month == 1)
		{
			_year--;
			_month = 12;
		}
		else
		{
			_month--;
		}
		_day += GetMonthDay(_year,_month);

	}
	return *this;
}

⑨前置 ++ 的重载(+1操作应该考虑天数为月末,月份为年末时的特殊情况,通过判断月末与年末,对指定的月份+1或年份+1,并置新月份=1)

//( + 1操作应该考虑天数为月末,月份为年末时的特殊情况,
//通过判断月末与年末,对指定的月份 + 1或年份 + 1,并置新月份 = 1)
Date& Date::operator++()// ++d => d.operator++(&d)
{
	_day++;
	if (_day > GetMonthDay(_year, _month))
	{
		_day -= GetMonthDay(_year, _month);
		_month++;
		if (_month > 12)
		{
			_year++;
			_month = 1;
		}
	}
	return *this;

}

⑩后置 ++ 的重载(后置++与前置++类似,返回值略有差异,可以拷贝构造一个临时的函数来保存this指针保存的内容,最终返回临时的函数)

//(后置++与前置++类似,返回值略有差异,
//可以拷贝构造一个临时的函数来保存this指针保存的内容,最终返回临时的函数)
Date Date::operator++(int)// d++ => d.operator(&d, 0)
{
	Date ret(*this);
	_day++;
	if (_day > GetMonthDay(_year, _month))
	{
		_day -= GetMonthDay(_year, _month);
		_month++;
		if (_month > 12)
		{
			_year++;
			_month = 1;
		}
	}
	return ret;

}

⑪前置 – 的重载(-1操作应该考虑天数为月初,月份为年初时的特殊情况,通过判断月末与年末,对指定的月份-1或年份-1,并置新月份=12)

// (-1操作应该考虑天数为月初,月份为年初时的特殊情况,
//通过判断月末与年末,对指定的月份-1或年份-1,并置新月份=12)
Date& Date::operator--() // --d 
{
	_day--;
	if (_day <= 0)
	{
		if (_month == 1)
		{
			_year--;
			_month = 12;
		}
		else
		{
			_month--;
		}
		_day += GetMonthDay(_year, _month);
	}
	return *this;
}

⑫后置 – 的重载(与前置–类似,可以使用拷贝构造函数构造一个临时的函数,最终返回临时函数即可)

//(与前置--类似,可以使用拷贝构造函数构造一个临时的函数,最终返回临时函数即可)
Date Date::operator--(int) // d--
{
	Date ret(*this);
	if (_day <= 0)
	{
		if (_month == 1)
		{
			_year--;
			_month = 12;
		}
		else
		{
			_month--;
		}
		_day += GetMonthDay(_year, _month);
	}
	return ret;
}

⑬关系运算符的重载

//日期类关系操作符重载
bool Date::operator>(const Date& d)
{
	if (_year > d._year)
	{
		return true;
	}
	else if (_year == d._year)
	{
		if (_month > d._month)
		{
			return true;
		}
		else if (_month == d. _month)
		{
			if (_day > d._day)
			{
				return true;
			}
		}
	}
	return false;
}
 
bool Date::operator==(const Date& d)
{
	return _year == d._year
		&& _month == d._month
		&& _day == d._day;
}

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

// d1 >= d2
bool Date::operator>=(const Date& d)
{
	return *this > d || *this == d;
}

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

⑭输出运算符 << 的重载(模拟cout输出)

// 重载输出 <<
ostream& operator<<(ostream& _cout, const Date& d)
{
	_cout << d._year << "-" << d._month << "-" << d._day << endl;
	return _cout;
}

⑮ 输入运算符 >> 的重载(模拟cin输入)

//重载输入>>
istream& operator>>(istream& _cin, Date& d)
{
	_cin >> d._year;
	_cin >> d._month;
	_cin >> d._day;
	return _cin;
}

⑯两个日期相隔天数 - 的重载(这里可以运用一个巧妙的方法,将当前对象拷贝构造为Max,引用对象拷贝构造为Min,如果Max<Min,调用库函数交换,并用一个状态量flag标记。再利用while循环,只要Max与Min不相等,Max–,计数器Count++,Count即为最终的相隔天数)

//(这里可以运用一个巧妙的方法,将当前对象拷贝构造为Max,引用对象拷贝构造为Min,
//如果Max<Min,调用库函数交换,并用一个状态量flag标记。再利用while循环,
//只要Max与Min不相等,Max--,计数器days++,days即为最终的相隔天数)
int Date::operator-(const Date& d)
{
	int flag = 1;
	Date Max(*this);
	Date Min(d);
	if ((*this) < d)
	{
		std::swap(Max, Min);
		flag = -1;
	}
	int days = 0;
	while (Max != Min)
	{
		--Max;
		++days;
	}
	return days*flag;
}

参考代码

Date.h
#pragma once

#include<iostream>
#include<Windows.h>
#include<cmath>
 
using namespace std;


//日期类实现操作符重载
class Date
{
public:
	 
	// 全缺省参数构造函数
	Date(int year = 1997, int month = 11, int day = 4)
		:_year(year)
		, _month(month)
		, _day(day)
	{
		//检查合法
		if (year >= 0
			&& _month > 0 && _month < 13
			&& _day > 0 && _day <= GetMonthDay(year, month))
		{
			_year = year;
			_month = month;
			_day = day;
		}
		else
		{
			cout << "Date Invalid" << endl;
		}
	}
	//析构函数
	~Date()
	{
		;
	}

	//拷贝构造函数:Date d3(d1)或者 Date d3 = d1
	Date(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
	//赋值操作符重载
	Date&  operator=(const Date& d)
	{
		if (this != &d)
		{
			_year = d._year;
			_month = d._month;
			_day = d._day;
		}
		return *this;
	}
	//取地址操作符重载
	Date* operator&()
	{
		return this;
	}

	//关系操作符重载
	bool operator>(const Date& d);
	bool operator<(const Date& d);
	bool operator<=(const Date& d);
	bool operator>=(const Date& d);
	bool operator==(const Date& d);
	bool operator!=(const Date& d);

	//获取当月天数
	int GetMonthDay(int year, int month);

	//返回自身加引用,返回临时值返回
	Date operator+(int day);
	Date& operator+=(int day);
	Date operator-(int day);
	Date& operator-=(int day);
	int operator-(const Date& d);
	Date& operator++();  
	Date operator++(int);  
	Date& operator--();  
	Date operator--(int);  

	//重载输出<<
	friend ostream& operator<<(ostream& _cout, const Date& d);

	//重载输入>>
	friend istream& operator>>(istream& _cin, Date& d);
	
private:
	int _year;
	int _month;
	int _day;
};

 
Date.cpp
#include "Date.h"

//获取当月天数
int Date::GetMonthDay(int year, int month)
{
	//方法一:十二个if、else语句
	//方法二:switch分支语句
	//此处方法三:
	 static const int days[13] = {0, 31,28, 31,30, 31,30, 31,31,30, 31,30, 31 };//润年二月多一天
	 //4年一润百年不润400年一润且此处至于二月有关
	 if ((month == 2)&&((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
	 {
		 return 29;

	 }
	 return days[month];
}

//日期类关系操作符重载
bool Date::operator>(const Date& d)
{
	if (_year > d._year)
	{
		return true;
	}
	else if (_year == d._year)
	{
		if (_month > d._month)
		{
			return true;
		}
		else if (_month == d. _month)
		{
			if (_day > d._day)
			{
				return true;
			}
		}
	}
	return false;
}
 
bool Date::operator==(const Date& d)
{
	return _year == d._year
		&& _month == d._month
		&& _day == d._day;
}

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

// d1 >= d2
bool Date::operator>=(const Date& d)
{
	return *this > d || *this == d;
}

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


//日期类操作符重载
// d1 + 100	  
//当+days大于该月总天数时,用days减去该月天数,月份month+1,差值即为新月份的天数。
//若遇到年末,即month = 12时,年份year++,月份month置1,否则month++)
Date Date::operator+(int day)
{
	Date ret(*this);

	/*if (day<0)
		return ret - abs(day);
	ret._day += day;

	while (ret._day > GetMonthDay(ret._year, ret._month))
	{
		ret._day -= GetMonthDay(ret._year,ret._month);
		if (12 == ret._month)
		{
			ret._year++;
			_month = 1;

		}
		else
		{
			_month += 1;
		}
	}*/
	//改进:
	ret += day;
	return ret;
}

Date& Date::operator+=(int day)
{
	if (day<0)
	{
		return *this - abs(day);
	}
	
	_day += day;
	while (_day > GetMonthDay(_year, _month))
	{
		_day -= GetMonthDay(_year, _month);
		if (12 == _month)
		{
			_year++;
			_month = 1;

		}
		else
		{
			_month += 1;
		}
	}
	return *this;
}
//(与+days类似,用该月天数-days,
//其差值若小于0,且在年初,则年份year--,置月份month=12,否则month--)
Date Date::operator-(int day)
{
	Date ret(*this);

	/*if (day < 0)
		return ret + abs(day);
	ret._day -= day;
	while (ret._day <= 0)
	{

		if (ret._month == 1)
		{
			ret._year--;
			ret._month = 12;
		}
		else
		{
			ret._month--;
		}
		ret._day += GetMonthDay(ret._year,ret._month);

	}*/
	//改进:
	ret -= day;
	return ret;
}
Date& Date::operator-=(int day)
{
	if (day < 0)
		return *this + abs(day);
	_day -= day;
	while (_day <= 0)
	{
		if (_month == 1)
		{
			_year--;
			_month = 12;
		}
		else
		{
			_month--;
		}
		_day += GetMonthDay(_year,_month);

	}
	return *this;
}
//(这里可以运用一个巧妙的方法,将当前对象拷贝构造为Max,引用对象拷贝构造为Min,
//如果Max<Min,调用库函数交换,并用一个状态量flag标记。再利用while循环,
//只要Max与Min不相等,Max--,计数器days++,days即为最终的相隔天数)
int Date::operator-(const Date& d)
{
	int flag = 1;
	Date Max(*this);
	Date Min(d);
	if ((*this) < d)
	{
		std::swap(Max, Min);
		flag = -1;
	}
	int days = 0;
	while (Max != Min)
	{
		--Max;
		++days;
	}
	return days*flag;
}
//( + 1操作应该考虑天数为月末,月份为年末时的特殊情况,
//通过判断月末与年末,对指定的月份 + 1或年份 + 1,并置新月份 = 1)
Date& Date::operator++()// ++d => d.operator++(&d)
{
	/*_day++;
	if (_day > GetMonthDay(_year, _month))
	{
		_day -= GetMonthDay(_year, _month);
		_month++;
		if (_month > 12)
		{
			_year++;
			_month = 1;
		}
	}*/
	//该进:
	*this += 1;
	return *this;

}
//(后置++与前置++类似,返回值略有差异,
//可以拷贝构造一个临时的函数来保存this指针保存的内容,最终返回临时的函数)
Date Date::operator++(int)// d++ => d.operator(&d, 0)
{
	Date ret(*this);
	/*_day++;
	if (_day > GetMonthDay(_year, _month))
	{
		_day -= GetMonthDay(_year, _month);
		_month++;
		if (_month > 12)
		{
			_year++;
			_month = 1;
		}
	}*/
	*this += 1;
	return ret;

}
// (-1操作应该考虑天数为月初,月份为年初时的特殊情况,
//通过判断月末与年末,对指定的月份-1或年份-1,并置新月份=12)
Date& Date::operator--() // --d 
{
	/*_day--;
	if (_day <= 0)
	{
		if (_month == 1)
		{
			_year--;
			_month = 12;
		}
		else
		{
			_month--;
		}
		_day += GetMonthDay(_year, _month);
	}*/
	*this -= 1;
	return *this;
}
//(与前置--类似,可以使用拷贝构造函数构造一个临时的函数,最终返回临时函数即可)
Date Date::operator--(int) // d--
{
	Date ret(*this);
	/*_day--;
	if (_day <= 0)
	{
		if (_month == 1)
		{
			_year--;
			_month = 12;
		}
		else
		{
			_month--;
		}
		_day += GetMonthDay(_year, _month);
	}*/
	*this -= 1;
	return ret;
}
// 重载输出 <<
ostream& operator<<(ostream& _cout, const Date& d)
{
	_cout << d._year << "-" << d._month << "-" << d._day << endl;
	return _cout;
}
//重载输入>>
istream& operator>>(istream& _cin, Date& d)
{
	_cin >> d._year;
	_cin >> d._month;
	_cin >> d._day;
	return _cin;
}
Main.cpp
#include "Date.h"
void FunTest()
{
	Date date1(2015, 3, 31);
	Date date2(date1);
	Date date3(2017, 12, 1);
	Date date4(date3);
	Date date5(2012, 2, 2);
	Date date6(date5);
	Date date7(2017, 2, 19);
	Date date8(2015, 8, 8);
	Date date9;

	cout<<"date1:"<<date1<<endl;
	cout<<"date2:"<<date2<<endl;
	cout<<"date3:"<<date3<<endl;
	cout<<"date4:"<<date4<<endl;
	cout<<"date5:"<<date5<<endl;
	cout<<"date6:"<<date6<<endl;
	cout<<"date7:"<<date7<<endl;
	cout<<"date8:"<<date8<<endl;
	cout<<"date9:"<<date9<<endl;

	cout << "前置++:" << ++date1 << endl;
	cout << "后置++:" << date2++ << endl;
	cout << "前置--:" << --date3 << endl;
	cout << "后置--:" << date4-- << endl;
	cout << "加指定天数:" << date5 + 24 << endl;
	cout << "减指定天数:" << date6 - 5 << endl;
	cout << "两个日期相差的天数:" << date7 - date8 << endl;
	
	cin>>date9;
}
int main()
{
	FunTest();
	system("pause");
	return 0;
}

效果样例:

在这里插入图片描述

结语

初识C++的大门,希望自己在这条路上越走越远!

猜你喜欢

转载自blog.csdn.net/qq_41035588/article/details/83247178
今日推荐