【C++】日期类

news2024/10/7 10:15:31

鼠鼠实现了一个日期类,用来练习印证前几篇博客介绍的内容!!

目录

1.日期类的定义 

2.得到某年某月的天数

 3.检查日期是否合法

 4.(全缺省)构造函数

5.拷贝构造函数 

6.析构函数

7.赋值运算符重载 

8.>运算符重载 

9.==运算符重载

 10.>=运算符重载

11.<运算符重载 

12.<=运算符重载 

13.!=运算符重载 

14.日期 += 天数 

15.日期+天数 

16.日期-=天数

17.日期-天数

18.前置++

19.后置++

20.前置-- 

21.后置--

22.日期-日期,返回天数 

 23.流插入运算符重载

24.流提取运算符重载 

25.test 


本鼠创建一个工程,工程包含三个文件,分别是Date.h、Date.cpp和test.cpp。 

1.日期类的定义 

本鼠对日期类的定义如下,放在了Date.h文件中:

class Date
{
	int _year;
	int _month;
	int _day;
public:
	inline int GetMonth_day()const//得到某年某月的天数
	{
		const int a[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
		if (this->_month == 2 && (this->_year % 4 == 0 && this->_year % 100 != 0 || this->_year % 400 == 0))
		{
			return 29;
		}
		return a[this->_month];
	}

	bool Check()const;//检查日期是否合法

	Date(int year = 1, int month = 1, int day = 1);//(全缺省)构造函数

	Date(const Date& d);//拷贝构造函数

	~Date();//析构函数

	Date& operator=(const Date& d)//赋值运算符重载
	{
		this->_year = d._year;
		this->_month = d._month;
		this->_day = d._day;
	}
	
	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);//日期-=天数

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

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

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

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

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

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


	friend ostream& operator<<(ostream& cout, const Date& d);//友元函数:流插入运算符重载
	friend istream& operator>>(istream& cin, Date& d);//友元函数:流提取运算符重载
};

本鼠对于成员函数大部分都采取声明和定义分离的方式。成员变量无非就是年、月、日呗。还运用了友元的知识。如上代码所示。

2.得到某年某月的天数

 对于这个日期类所要实现的成员函数中有很多场景我们需要得到某年某月的天数,所以我们将这个功能实现成函数。又因为需要频繁调用这个函数,我们将他实现成内联函数。

声明和定义:

inline int GetMonth_day()const//得到某年某月的天数

	{
		const int a[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
		if (this->_month == 2 && (this->_year % 4 == 0 && this->_year % 100 != 0 || this->_year % 400 == 0))
		{
			return 29;
		}
		return a[this->_month];
	}

注意:

  • 该函数的实现思路过于简单,本鼠就不解释了!
  • 内联函数声明和定义不可分离,又因为日期类的成员函数需频繁调用这个函数,所以我们将其声明和定义都实现在类里面。
  • 这是一个对this指针指向对象的成员变量只进行读访问的函数,所以我们将其实现成const成员函数。

 3.检查日期是否合法

例如构造函数可能构造了非法的日期,所以我们将检查日期是否合法这个功能实现成函数。

定义:

bool Date::Check()const//检查日期是否合法
{
	if (this->_year < 0 ||
		this->_month < 0 || this->_month > 12 ||
		this->_day<0 || this->_day>GetMonth_day())
	{
		return true;
	}
	return false;
}

注意:

  • 该函数的实现思路:我们这个日期类不支持公元前的年份。所以当this指针指向对象的日期:年小于0、月小于0、月大于12、日小于0、日大于该日期应得天数这几项但凡有一项为真时,说明日期非法,返回真;否则,返回假。
  • 该函数声明和定义分离,所以定义成员函数时,成员函数名前需要加Date::,成员函数定义在Date.cpp文件中。
  • 这是一个对this指针指向对象的成员变量只进行读访问的函数,所以我们将其实现成const成员函数。

 4.(全缺省)构造函数

我们分析日期类对象的初始化需求,若使用编译器生成的默认构造函数是达不到需求的,所以我们自己显式实现构造函数。

定义:

Date::Date (int year , int month , int day )//(全缺省)构造函数
{
	this->_year = year;
	this->_month = month;
	this->_day = day;
	if (Check())
	{
		cout << "构造了日期非法:" << *this << endl;
	}
}

注意:

  • 该函数的实现思路无非就是将第2、3、4个形参的年、月、日初始化this指针指向对象的成员变量(年、月、日),若形参没有接收到实参的拷贝,使用缺省值。
  • 需要检查this指针指向对象的日期是否合法。
  • 该函数声明和定义分离,所以定义成员函数时,成员函数名前需要加Date::,成员函数定义在Date.cpp文件中。
  • 缺省参数不能在函数声明和定义中同时出现,当函数声明和定义分离时在声明给缺省参数 。
  • 这是一个对this指针指向对象的成员变量要进行读写访问的成员函数,不能实现成const成员函数。

5.拷贝构造函数 

这个日期类不涉及资源申请,其实不用我们显式实现拷贝构造函数,用编译器生成的默认拷贝构造函数就行 ,本鼠显式实现就是练练手。

定义:

Date::Date(const Date& d)//拷贝构造函数
{
	this->_year = d._year;
	this->_month = d._month;
	this->_day = d._day;
}

注意:

  • 该函数的实现思路:第一个形参是隐藏的this指针,第二个形参是已存在对象的引用。 用第二个形参的成员变量初始化this指针指向的正在创建对象的成员变量。
  • 该函数声明和定义分离,所以定义成员函数时,成员函数名前需要加Date::,成员函数定义在Date.cpp文件中。
  • 这是一个对this指针指向对象的成员变量要进行读写访问的成员函数,不能实现成const成员函数。

6.析构函数

这个日期类的析构函数其实也不用我们自己显式实现的,练练手。

定义:

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

注意:

  • ​​​不妨将this指针指向对象的成员变量赋值成0就行 ,其实函数体内为空也无妨。反正这个日期类没有申请资源,当对象生命周期结束后系统会将其内存收归就行。
  • 该函数声明和定义分离,所以定义成员函数时,成员函数名前需要加Date::,成员函数定义在Date.cpp文件中。
  • 这是一个对this指针指向对象的成员变量要进行读写访问的成员函数,不能实现成const成员函数。

7.赋值运算符重载 

其实这个函数也不用我们自己显式实现的,练练手。

 声明和定义:

	Date& operator=(const Date& d)//赋值运算符重载
	{
		this->_year = d._year;
		this->_month = d._month;
		this->_day = d._day;
		return *this;
	}

注意:

  • 该函数实现思路:第二个形参是已存在对象的引用。用第二个形参的成员变量赋值给this指针指向对象的成员变量就行。
  • 为了支持连续赋值,需要返回左操作数本身(拷贝也行)。
  • 赋值运算符只能重载成类的成员函数不能重载成全局函数。
  • 这是一个对this指针指向对象的成员变量要进行读写访问的成员函数,不能实现成const成员函数。

8.>运算符重载 

定义:

bool Date::operator>(const Date& d)const//>运算符重载
{
	if (this->_year > d._year)
	{
		return true;
	}
	else if (this->_year == d._year)
	{
		if (this->_month > d._month)
		{
			return true;
		}
		else if (this->_month == d._month)
		{
			return this->_day > this->_day;
		}
	}
	return false;
}

注意:

  • 该函数的第一个形参this指针为第一个操作数的地址,第二个形参为第二个操作数的引用。
  • 该函数的实现思路:若第一个操作数的年大于第二个操作数的年,返回真;若第一个操作数的年等于第二个操作数的年,那就若第一个操作数的月大于第二个操作数的月,返回真;若第一个操作数的年和月都等于第二个操作数的年和月,那就若第一个操作数的日大于第二个操作数的日,返回真;其余情况都返回假。
  • 该函数声明和定义分离,所以定义成员函数时,成员函数名前需要加Date::,成员函数定义在Date.cpp文件中。
  • 这是一个对this指针指向对象的成员变量只进行读访问的函数,所以我们将其实现成const成员函数。

9.==运算符重载

定义:

bool Date::operator==(const Date& d)const//==运算符重载
{
	return this->_year == d._year && this->_month == d._month && this->_day == d._day;
}

注意: 

  •  该函数的第一个形参this指针为第一个操作数的地址,第二个形参为第二个操作数的引用。
  • 该函数实现思路:第一个操作数的年、月、日都等于第二个操作数的年、月、日,返回真;否则,返回假。
  • 该函数声明和定义分离,所以定义成员函数时,成员函数名前需要加Date::,成员函数定义在Date.cpp文件中。
  • 这是一个对this指针指向对象的成员变量只进行读访问的函数,所以我们将其实现成const成员函数。

 10.>=运算符重载

定义:

bool Date:: operator>=(const Date& d)const//>=运算符重载
{
	return *this > d || *this == d;
}

注意: 

  •  该函数的第一个形参this指针为第一个操作数的地址,第二个形参为第二个操作数的引用。
  • 该函数的实现思路:若第一个操作数大于或者等于第二个操作数(调用>运算符重载和==运算符重载),返回真;否则,返回假。
  • 该函数声明和定义分离,所以定义成员函数时,成员函数名前需要加Date::,成员函数定义在Date.cpp文件中。
  • 这是一个对this指针指向对象的成员变量只进行读访问的函数,所以我们将其实现成const成员函数。

11.<运算符重载 

定义:

bool Date::operator<(const Date& d)const//<运算符重载
{
	return !(*this >= d);
}

 注意:

  • 该函数的第一个形参this指针为第一个操作数的地址,第二个形参为第二个操作数的引用。
  • 该函数的实现思路:返回>=运算符重载的逻辑取反就好。
  • 该函数声明和定义分离,所以定义成员函数时,成员函数名前需要加Date::,成员函数定义在Date.cpp文件中。
  • 这是一个对this指针指向对象的成员变量只进行读访问的函数,所以我们将其实现成const成员函数。

12.<=运算符重载 

定义:

bool Date::operator<=(const Date& d)const//<=运算符重载
{
	return !(*this > d);
}

注意:

  • 该函数的第一个形参this指针为第一个操作数的地址,第二个形参为第二个操作数的引用。
  • 该函数的实现思路:返回>运算符重载的逻辑取反就好。
  • 该函数声明和定义分离,所以定义成员函数时,成员函数名前需要加Date::,成员函数定义在Date.cpp文件中。
  • 这是一个对this指针指向对象的成员变量只进行读访问的函数,所以我们将其实现成const成员函数。

13.!=运算符重载 

定义:

bool Date::operator!=(const Date& d)const//!=运算符重载
{
	return !(*this == d);
}

注意:

  • 该函数的第一个形参this指针为第一个操作数的地址,第二个形参为第二个操作数的引用。
  • 该函数的实现思路:返回==运算符重载的逻辑取反就好。
  • 该函数声明和定义分离,所以定义成员函数时,成员函数名前需要加Date::,成员函数定义在Date.cpp文件中。
  • 这是一个对this指针指向对象的成员变量只进行读访问的函数,所以我们将其实现成const成员函数。

14.日期 += 天数 

这个函数本鼠想要的是日期+天数后,日期本身发生改变形成新日期并返回。 

定义:

Date& Date::operator+=(int day) //日期 += 天数
{
	this->_day += day;
	while (this->_day > GetMonth_day())
	{
		this->_day -= GetMonth_day();
		this->_month++;
		if (this->_month > 12)
		{
			this->_month = 1;
			this->_year++;
		}
	}
	return *this;
}

注意:

  • 该函数的实现思路: this指针指向对象的日期的日+=天数。循环:日若超过“当年当月”该有的天数,说明月该+1;就让日-“当年当月”该有的天数,并++月;若是月超过12,年份就该+1;…………直到日小于“当年当月”该有的天数循环停止。思想本质就跟我们做加法运算是一样的,有时又要向高位进位。。
  • 该函数的返回值*this出了该函数作用域还存在,可以用引用返回。
  • 该函数声明和定义分离,所以定义成员函数时,成员函数名前需要加Date::,成员函数定义在Date.cpp文件中。
  • 这是一个对this指针指向对象的成员变量要进行读写访问的成员函数,不能实现成const成员函数。

15.日期+天数 

这个函数本鼠想要的是日期+天数后,日期本身不发生改变,却要返回日期+天数后的结果。

定义:

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

注意:

  • 该函数的实现思路:通过拷贝构造函数创建一个与this指针指向对象一样的临时对象,让临时对象+=天数,返回临时对象就好了。
  • 该函数的返回值是临时对象,出了该函数的作用域就不存在了,所以不能用引用返回。
  • 该函数声明和定义分离,所以定义成员函数时,成员函数名前需要加Date::,成员函数定义在Date.cpp文件中。
  • 这是一个对this指针指向对象的成员变量只进行读访问的函数,所以我们将其实现成const成员函数。

16.日期-=天数

这个函数本鼠想要的是日期-天数后,日期本身发生改变形成新日期并返回。 

定义:

Date& Date::operator-=(int day)//日期-=天数
{
	this->_day -= day;
	while (this->_day <= 0)
	{
		this->_month--;
		if (this->_month < 1)
		{
			this->_year--;
			this->_month = 12;
		}
		this->_day += GetMonth_day();
	}
	return *this;
}

注意:

  • 该函数的实现思路:this指针指向对象的日-=天数。循环:日若小于或等于0,说明月该-1;月--后需要判断月是否小于1,如果月小于1,年份就该-1;日+=“当年当月”该有的天数;…………直到日大于0循环停止。思想本质跟我们做减法运算是一样的,有时候要跟高位借位呗。。
  • 该函数的返回值*this出了该函数作用域还存在,可以用引用返回。
  • 该函数声明和定义分离,所以定义成员函数时,成员函数名前需要加Date::,成员函数定义在Date.cpp文件中。
  • 这是一个对this指针指向对象的成员变量要进行读写访问的成员函数,不能实现成const成员函数。

17.日期-天数

这个函数本鼠想要的是日期-天数后,日期本身不发生改变,却要返回日期-天数后的结果。

定义:

Date Date::operator-(int day)const//日期-天数
{
	Date tmp = *this;
	tmp -= day;
	return tmp;
}
  • 该函数的实现思路:通过拷贝构造函数创建一个与this指针指向对象一样的临时对象,让临时对象-=天数,返回临时对象就好了。
  • 该函数的返回值是临时对象,出了该函数的作用域就不存在了,所以不能用引用返回。
  • 该函数声明和定义分离,所以定义成员函数时,成员函数名前需要加Date::,成员函数定义在Date.cpp文件中。
  • 这是一个对this指针指向对象的成员变量只进行读访问的函数,所以我们将其实现成const成员函数。

18.前置++

前置++:日期本身+1,返回日期+1之后的结果。

定义:

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

注意:

  • 这个函数实现思想过于简单,不解释了。
  •  该函数的返回值*this出了该函数作用域还存在,可以用引用返回。
  • 该函数声明和定义分离,所以定义成员函数时,成员函数名前需要加Date::,成员函数定义在Date.cpp文件中。
  • 这是一个对this指针指向对象的成员变量要进行读写访问的成员函数,不能实现成const成员函数。

19.后置++

后置++:先使用后+1,因此需要返回+1之前的旧值。日期本身+1,返回日期+1之前的旧日期。

定义:

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

注意:

  • 这个函数实现思想过于简单,不解释。
  • 后置++重载时多增加一个int类型的参数,不显式调用函数时该参数不用传递,编译器自动传递;显式调用该函数,那么一定要传入一个任意int整形以区分前置++。
  • 这个函数的返回值是临时变量,出了该函数作用域就不存在了,所以不能用引用返回。
  •  该函数声明和定义分离,所以定义成员函数时,成员函数名前需要加Date::,成员函数定义在Date.cpp文件中。
  • 这是一个对this指针指向对象的成员变量要进行读写访问的成员函数,不能实现成const成员函数。

20.前置-- 

前置--:日期本身-1,返回日期-1之后的结果。

定义:

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

注意:

  • 这个函数实现思想过于简单,不解释了。
  •  该函数的返回值*this出了该函数作用域还存在,可以用引用返回。
  • 该函数声明和定义分离,所以定义成员函数时,成员函数名前需要加Date::,成员函数定义在Date.cpp文件中。
  • 这是一个对this指针指向对象的成员变量要进行读写访问的成员函数,不能实现成const成员函数。

21.后置--

后置--:先使用后-1,因此需要返回-1之前的旧值。日期本身-1,返回日期-1之前的旧日期。

定义:

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

注意:

  • 这个函数实现思想过于简单,不解释。
  • 后置--重载时多增加一个int类型的参数,不显式调用函数时该参数不用传递,编译器自动传递;显式调用该函数,那么一定要传入一个任意int整形以区分前置--。
  • 这个函数的返回值是临时变量,出了该函数作用域就不存在了,所以不能用引用返回。
  •  该函数声明和定义分离,所以定义成员函数时,成员函数名前需要加Date::,成员函数定义在Date.cpp文件中。
  • 这是一个对this指针指向对象的成员变量要进行读写访问的成员函数,不能实现成const成员函数。

22.日期-日期,返回天数 

这个函数本鼠想要获取日期之间夹杂着多少天呗。如果第一个日期大于第二个日期,返回的天数是负数;反之,为正数。

定义:

int Date::operator-(const Date& d)const//日期-日期,返回天数
{
	Date max = *this;
	Date min = d;
	int flag = -1;
	if (max < min)
	{
		flag = 1;
		max = d;
		min = *this;
	}
	int n = 0;
	while (max != min)
	{
		min++;
		n++;
	}
	return n * flag;
}

注意: 

  • 这个函数实现思路简单,本鼠就不解释了。
  •  该函数声明和定义分离,所以定义成员函数时,成员函数名前需要加Date::,成员函数定义在Date.cpp文件中。
  • 这是一个对this指针指向对象的成员变量只进行读访问的函数,所以我们将其实现成const成员函数。

 23.流插入运算符重载

介绍流插入运算符重载之前,我们需要回顾这里C++的输入&&输出介绍过的知识:cout是库里面的ostream类型的全局对象。

对于流插入运算符重载,本鼠并没有将其重载成日期类的成员函数,而是重载成全局函数,为啥?


我们先看流插入运算符一般的使用场景如下:

#include<iostream>
using namespace std;
int main()
{
	int a = 10;
	int b = 20;
	cout << a << ' ' << b << endl;
	return 0;
}

我们分析:

  • 分析1:对于流插入操作符<<来说,是有两个操作数的,第一个应该对象cout,第二个是需要“流向”控制台的对象
  • 分析2:流插入操作符<<需要支持连续输出,如这里:
cout << a << ' ' << b << endl;

这句语句的结合性是从左往右的,cout<<a的返回值是对象cout,这个返回值cout又作为cout<<' '的左操作数,cout<<' '的返回值又是对象cout,这个返回值cout又作为cout<<b的左操作数…………

如果我们将流插入运算符重载重载成日期类的成员函数的话,我们想想当我们在主函数调用的情景必然是这样的:

int main()
{
	Date d1;
	d1.operator<<(cout);//显式调用
	d1. << cout;//不显式调用
	return 0;
}

可是这样子的话代码的可读性不好,好像是cout通过<<“流向” d1一样。不符合我们对分析1的分析。


那该如何是好呢?其中一个办法就是将流插入运算符重载重载成全局函数。

那么将其重载成全局函数的话,也采用声明和定义分离,为了支持连续输出,返回值应该是对象cout。

声明,声明在Date.h文件中:

ostream& operator<<(ostream& cout, const Date& d);//流插入运算符重载

定义,定义在Date.cpp文件中:

ostream& operator<<(ostream& cout, const Date& d)//流插入
{
	cout << d._year << '/' << d._month << '/' << d._day ;
	return cout;
}

我们没有将其重载成全局函数,日期类的成员变量又是被访问限定符private修饰的,那么在这个全局函数中无权访问对象的成员变量啊。所以我们在日期类中用到友元函数:

friend ostream& operator<<(ostream& cout, const Date& d);//友元函数:流插入运算符重载

24.流提取运算符重载 

 介绍流提取运算符重载之前,我们需要回顾这里C++的输入&&输出介绍过的知识:cin是库里面的istream类型的全局对象。

流提取运算符重载的问题和流插入运算符重载的问题差不多,不介绍了。

流提取运算符重载重载成全局函数,采取声明和定义分离,为了支持连续输入,返回值应该是对象cin。

声明,声明在Date.h文件中:

ostream& operator<<(ostream& cout, const Date& d);//流插入运算符重载

定义,定义在Date.cpp文件中:

istream& operator>>(istream& cin,  Date& d)//流提取
 {
	 cout << "请输入日期并以回车键结束" << endl;
	 while (1)
	 {
		 cin >> d._year >> d._month >> d._day;
		 if (d.Check())
		 {
			 cout << "输入日期非法" << endl;
		 }
		 else
		 {
			 break;
		 }
	 }
	 return cin;
 }

不同的是,这里流提取可以给一定的提示,如:请输入日期并以回车键结束。检查输入的日期是否合法也是必须的。

日期类中用到友元函数:

friend istream& operator>>(istream& cin, Date& d);//友元函数:流提取运算符重载

25.test 

 全部代码如下,可以在test.cpp中测试代码,有兴趣可以玩玩。

Date.h:

#pragma once
#include<stdbool.h>
#include<iostream>
using namespace std;
class Date
{
	int _year;
	int _month;
	int _day;
public:
	inline int GetMonth_day()const//得到某年某月的天数
	{
		const int a[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
		if (this->_month == 2 && (this->_year % 4 == 0 && this->_year % 100 != 0 || this->_year % 400 == 0))
		{
			return 29;
		}
		return a[this->_month];
	}

	bool Check()const;//检查日期是否合法

	Date(int year = 1, int month = 1, int day = 1);//(全缺省)构造函数

	Date(const Date& d);//拷贝构造函数

	~Date();//析构函数

		Date& operator=(const Date& d)//赋值运算符重载
	{
		this->_year = d._year;
		this->_month = d._month;
		this->_day = d._day;
		return *this;
	}
	
	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);//日期-=天数

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

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

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

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

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

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


	friend ostream& operator<<(ostream& cout, const Date& d);//友元函数:流插入运算符重载
	friend istream& operator>>(istream& cin, Date& d);//友元函数:流提取运算符重载
};


ostream& operator<<(ostream& cout, const Date& d);//流插入运算符重载

istream& operator>>(istream& cin,  Date& d);//流提取运算符重载

Date.cpp:

#include"Date.h"
bool Date::Check()const//检查日期是否合法
{
	if (this->_year < 0 ||
		this->_month < 0 || this->_month > 12 ||
		this->_day<0 || this->_day>GetMonth_day())
	{
		return true;
	}
	return false;
}

Date::Date (int year , int month , int day )//(全缺省)构造函数
{
	this->_year = year;
	this->_month = month;
	this->_day = day;
	if (Check())
	{
		cout << "构造了日期非法:" << *this << endl;
	}
}

Date::Date(const Date& d)//拷贝构造函数
{
	this->_year = d._year;
	this->_month = d._month;
	this->_day = d._day;
}

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

bool Date::operator>(const Date& d)const//>运算符重载
{
	if (this->_year > d._year)
	{
		return true;
	}
	else if (this->_year == d._year)
	{
		if (this->_month > d._month)
		{
			return true;
		}
		else if (this->_month == d._month)
		{
			return this->_day > this->_day;
		}
	}
	return false;
}

bool Date::operator==(const Date& d)const//==运算符重载
{
	return this->_year == d._year && this->_month == d._month && this->_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) //日期 += 天数
{
	this->_day += day;
	while (this->_day > GetMonth_day())
	{
		this->_day -= GetMonth_day();
		this->_month++;
		if (this->_month > 12)
		{
			this->_month = 1;
			this->_year++;
		}
	}
	return *this;
}

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

Date& Date::operator-=(int day)//日期-=天数
{
	this->_day -= day;
	while (this->_day <= 0)
	{
		this->_month--;
		if (this->_month < 1)
		{
			this->_year--;
			this->_month = 12;
		}
		this->_day += GetMonth_day();
	}
	return *this;
}

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

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

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 (max < min)
	{
		flag = 1;
		max = d;
		min = *this;
	}
	int n = 0;
	while (max != min)
	{
		min++;
		n++;
	}
	return n * flag;
}

 ostream& operator<<(ostream& cout, const Date& d)//流插入
{
	cout << d._year << '/' << d._month << '/' << d._day ;
	return cout;
}

 istream& operator>>(istream& cin,  Date& d)//流提取
 {
	 cout << "请输入日期并以回车键结束" << endl;
	 while (1)
	 {
		 cin >> d._year >> d._month >> d._day;
		 if (d.Check())
		 {
			 cout << "输入日期非法,请重新输入" << endl;
		 }
		 else
		 {
			 break;
		 }
	 }
	 return cin;
 }

test.cpp:

#include"Date.h"
int main()
{
	Date d1(2003, 12, 12);
	Date d2 = d1;
	cout << d1 << endl << d2 << endl;
	cout << (d1 > d2) << endl;
	cout << (d1 >= d2) << endl;
	cout << (d1 < d2) << endl;
	cout << (d1 <= d2) << endl;
	cout << (d1 == d2) << endl;
	cout << (d1 != d2) << endl;
	Date d3;
	cout << d3 << endl;
	cin >> d3 >> d2 >> d1;
	cout << d3 <<endl<< d2 <<endl<< d1 << endl;
	return 0;
}

 运行结果,符合预期:

 感谢阅读!!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1898340.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【论文阅读】VASA-1: Lifelike Audio-Driven Talking FacesGenerated in Real Time

整体框架。不直接生成视频帧&#xff0c;而是在潜在空间中生成整体面部动态和头部运动&#xff0c;条件是音频和其他信号。给定这些运动潜在编码&#xff0c;通过面部解码器生成视频帧&#xff0c;还接受从输入图像中提取的外观和身份特征作为输入。 构建了一个面部潜在空间并…

JMH320【亲测】【御剑九歌】唯美仙侠手游御剑九歌+WIN学习手工端+视频教程+开服清档+运营后台+授权GM物品充值后台

资源介绍&#xff1a; 这也是仙梦奇缘的一个游戏 注意&#xff1a;外网14位IP或域名 ———————————————————————————————————– ps后台介绍: 1区运营后台&#xff1a;http://ip:9981/admin/admintool/ 2区运营后台&#xff1a;http://ip…

Finding Global Homophily in Graph Neural Networks When Meeting Heterophily

本文发表于:ICML22 推荐指数: #paper/⭐⭐⭐ 问题背景: 异配图的邻接矩阵难以确定,以及异配图的计算复杂度开销大 可行的解决办法:高通滤波多跳邻居,GPRGNN(pagerank一类&#xff0c;各阶邻居的权重不同,ACM-GCN&#xff08;高低通滤波,H2GCN&#xff08;应该复杂度很大&…

阶段总结——基于深度学习的三叶青图像识别

阶段总结——基于深度学习的三叶青图像识别 文章目录 一、计算机视觉图像分类系统设计二、训练模型2.1. 构建数据集2.2. 网络模型选择2.3. 图像数据增强与调参2.4. 部署模型到web端2.5. 开发图像识别小程序 三、实验结果3.1. 模型训练3.2. 模型部署 四、讨论五、参考文献&#…

Rocky Linux 9.4基于官方源码制作openssh 9.8p1二进制rpm包 —— 筑梦之路

2024年7月1日&#xff0c;openssh 9.8版本发布&#xff0c;主要修复了CVE-2024-6387安全漏洞。 由于centos 7的生命周期在6月30日终止&#xff0c;因此需要逐步替换到Rocky Linux&#xff0c;后续会有更多分享关于Rocky Linux的文章。 环境说明 1. 操作系统版本 cat /etc/o…

GuLi商城-商品服务-API-品牌管理-效果优化与快速显示开关

<template><div class"mod-config"><el-form :inline"true" :model"dataForm" keyup.enter.native"getDataList()"><el-form-item><el-input v-model"dataForm.key" placeholder"参数名&qu…

ASUS/华硕枪神5 G533Q G733Q系列 原厂win10系统 工厂文件 带F12 ASUS Recovery恢复

华硕工厂文件恢复系统 &#xff0c;安装结束后带隐藏分区&#xff0c;一键恢复&#xff0c;以及机器所有驱动软件。 系统版本&#xff1a;Windows10 原厂系统下载网址&#xff1a;http://www.bioxt.cn 需准备一个20G以上u盘进行恢复 请注意&#xff1a;仅支持以上型号专用…

(仿真+报告+源码)基于51单片机的温湿度监测系统

&#xff08;仿真报告源码&#xff09;基于51单片机的温湿度监测系统 付费后获得百度网盘链接&#xff0c;网盘链接在最后&#xff0c;有问题私信哦~~~ 一.系统简介 该系统由单片机、温湿度传感器器、液晶显示器以及浇水控制电路组成。该系统使用AT89C51单片机作为控制核心&…

JavaScript(6)——数据类型转换

为什么需要类型转换&#xff1f; JavaScript是弱数据类型&#xff1a;JavaScript不知道变量到底属于哪种数据类型&#xff0c;只有赋值了才清除 使用表单&#xff0c;prompt获取的数据默认为字符串类型&#xff0c;此时不能直接进行算数运算 隐式转换 某些运算符被执行时&am…

常规情况与opencv图像中,计算直线与矩形框的交点

文章目录 1、普通方式1.1、普通计算过程1.2、优化方式 2、图像中的情况2.1、常规处理2.2、opencv中的处理2.2.1、cv::clipLine函数2.2.2、测试代码2.2.3、测试结果 1、普通方式 已知矩形框左上(x1,y1)、右下(x2,y2&#xff09;点&#xff0c;直线方程 y kxb&#xff0c;求交点…

Ubuntu / Debian安装FTP服务

本章教程,记录在Ubuntu中安装FTP服务的具体步骤。FTP默认端口:21 1、安装 pure-ftpd sudo apt-get install pure-ftpd2、修改默认配置 # 与 centos 不同,这里需要在 /etc/pure-ftpd/conf 文件夹下执行下列命令,增加对应配置文件: # 创建 /etc/pure-ftpd/conf/PureDB 文件…

4.2 投影

一、投影和投影矩阵 我们以下面两个问题开始&#xff0c;问题一是为了展示投影是很容易视觉化的&#xff0c;问题二是关于 “投影矩阵”&#xff08;projection matrices&#xff09;—— 对称矩阵且 P 2 P P^2P P2P。 b \boldsymbol b b 的投影是 P b P\boldsymbol b Pb。…

金属3D打印如何精准选材

随着3D打印技术的飞跃发展&#xff0c;模具制造领域迎来了前所未有的创新机遇。在众多3D打印技术中&#xff0c;SLM金属3D打印以其精度高、复杂结构成型能力&#xff0c;成为众多行业的优选。然而&#xff0c;金属打印材料&#xff0c;如何精准选择&#xff0c;以最大化满足项目…

ASP.NET MVC-razor编写-2-svg中使用js+添加事件监听

环境&#xff1a;win10 效果 初始状态&#xff1a; 鼠标移入某个text&#xff08;比如KS primer&#xff09;时&#xff0c;text和连接的线条与箭头都变色&#xff1a; 鼠标移出时回复正常。 如果是移入另一种红色的text&#xff08;比如Cell Sceening Tag&#xff09;&…

Python学习笔记29:进阶篇(十八)常见标准库使用之质量控制中的数据清洗

前言 本文是根据python官方教程中标准库模块的介绍&#xff0c;自己查询资料并整理&#xff0c;编写代码示例做出的学习笔记。 根据模块知识&#xff0c;一次讲解单个或者多个模块的内容。 教程链接&#xff1a;https://docs.python.org/zh-cn/3/tutorial/index.html 质量控制…

【数据结构】(6.2)堆的应用——Top-K问题(C语言)

系列文章目录 文章目录 系列文章目录问题引入一、TopK 问题 是什么&#xff1f;二、TopK 问题解决思路2.1 TopK 思路2.2 随机产生数字2.2 完整代码2.3 验证结果 问题引入 TopK 问题 (在一堆数据里面找到前 K 个最大 / 最小的数)。 一、TopK 问题 是什么&#xff1f; 生活中也…

太速科技-FMC209-基于FMC的4路125MAD输入、2路1GDA输出子卡

FMC209-基于FMC的4路125MAD输入、2路1GDA输出子卡 一、板卡概述 本子卡基于FMC连接器实现4路125M采样率AD输出&#xff0c;两路1G采样率DA输出子卡&#xff0c;板卡默认由FMC连接器12V供电&#xff0c;支持外参考时钟&#xff0c;外输入时钟&#xff0c;外触发。 …

全端面试题15(canvas)

在前端开发领域&#xff0c;<canvas> 元素和相关的 API 是面试中经常被提及的主题。下面是一些常见的关于 HTML5 Canvas 的面试问题及解答示例&#xff1a; 1. 什么是 <canvas> 元素&#xff1f; <canvas> 是 HTML5 引入的一个用于图形渲染的标签。它本身并…

使用ChatGPT写论文,只需四步突破论文写作瓶颈!

欢迎关注&#xff0c;为大家带来最酷最有效的智能AI学术科研写作攻略。关于使用ChatGPT等AI学术科研的相关问题可以和作者七哥&#xff08;yida985&#xff09;交流 地表最强大的高级学术AI专业版已经开放&#xff0c;拥有全球领先的GPT学术科研应用&#xff0c;有兴趣的朋友可…

RT-Thread和freeRTOS启动流程

一. freeRTOS启动流程 二. RT-Thread启动流程 因为RT-Thread中我们定义了补丁函数也叫做钩子函数--$Sub$$main()--作为一个新功能函数&#xff0c;可以将原有函数劫持下来&#xff0c;并在之后的程序运行中加上$Super $ $前缀来重新调用原始函数。 所以启动流程是$Sub$$main(…