【C++入门-类与对象-日期类】

本文详细介绍了C++中日期类的实现,包括日期类的定义、成员函数如赋值、加减运算及流操作符重载。通过实例展示了如何判断闰年、获取月日数,以及处理日期合法性的检查。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

请添加图片描述



前言

本文总结学习日期类(c++实现)。


一、日期类头文件Date.h

本节主要包含:类的创建,部分成员函数声明,部分成员函数定义,成员变量的声明,头文件包含

#pragma once

#include <iostream>

using std::cout;
using std::cin;
using std::endl;


class Date
{
public:

	// 判断闰年
	bool Isleapyear(int year)
	{
		if ((0 == year % 4 && 0 != year % 100) || (0 == year % 400))
		{
			return true;
		}
		return false;
	}


	// 获取该月的天数
	size_t GetMonthDay(int year, int month)
	{
		// 2月的天数先默认取为平年的28天
		int MonthDay[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

		if (2 == month && Isleapyear(year))
		{
			MonthDay[2]++;
		}

		return MonthDay[month];
	}


	// 构造函数需自己写(成员变量全为内置类型,编译器默认生成的默认构造函数对内置类型不处理)
	
	// 1-初始化列表初始化,这样无法判断非法日期
	/*Date(int year, int month, int day)
		:_year(year)
		,_month(month)
		,_day(day)
	{}*/

	// 2-构造函数初始化
	Date(int year = 1, int month = 1, int day = 1)// 这里写为构造函数或者默认构造函数(不用传参就可以调用)都可以
	{
		// 判断日期的合法性
		if (year >= 1 && month >= 1 && month <= 12 && day >= 1 && day <= GetMonthDay(year, month))
		{
			this->_year = year;
			this->_month = month;
			this->_day = day;
		}
		else
		{
			cout << "日期非法" << endl;
		}
	}
	

	// 析构函数无须自己写(成员变量均为内置类型,无须资源清理,编译器默认生成的默认析构函数足以)


	// 拷贝构造函数无需自己写(成员变量均为内置类型,无须深拷贝,编译器默认生成的默认拷贝构造函数足以)


	// 打印
	void Print()const// this指向的对象无须修改,加const
	{
		cout << this->_year << "-" << this->_month << "-" << this->_day << endl;
	}


	// 赋值运算符重载,日期=日期
	const Date& operator=(const Date& d);


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

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

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

	// 日期-天数   同上


	// ++日期
	Date& operator++();

	// 日期++
	Date operator++(int);

	// ++日期
	// 日期--   同上


	// 日期>日期?
	bool operator>(const Date& d)const;

	// 日期==日期?
	bool operator==(const Date& d)const;

	// 日期>=日期?
	bool operator>=(const Date& d)const;

	// 日期!=日期?
	bool operator!=(const Date& d)const;

	// 日期<日期 日期<=日期 同上


	// 日期-日期
	int operator-(const Date& d)const;


	// 流提取操作符
	friend std::ostream& operator<<(std::ostream& out, const Date& d);// 不太理解!!!!!!!!!!!!!

	// 流插入操作符
	friend std::istream& operator>>(std::istream& in, Date& d);// 不太理解!!!!!!!!!!!!!
		
private:
	// 成员变量
	int _year;
	int _month;
	int _day;
};

二、日期类成员函数具体实现Date.c

本节主要包含:部分成员函数的定义

2.1 日期=日期

// 赋值运算符重载,d2 = d1 -> d2.operator(d1) -> d2.operator(&d2, d1)
// this指向的对象需要改,不加const
// 相当于const Date& opeator=(Date* const this,const Date& d1),d不修改所以加const

const Date& Date::operator=(const Date& d)
{
	// 判定不是自我赋值
	if (this != &d)
	{
		this->_year = d._year;
		this->_month = d._month;
		this->_day = d._day;
	}

	return *this;
}

2.2 日期+=天数

// 日期+=天数,d2 += 1 -> d2.operator(1) -> d2.operator(&d2, 1)
// this指向的对象需要改,不加const
// 相当于Date& operator+=(Date* const this, int day)
// 返回类型不用const Date&,因为定义对象如果不是const对象,接收会使得权限缩小

Date& Date::operator+=(int day) // 返回值改为void也可以?返回值有什么用???????????????应该是为了连续赋值
{
	// 先构造临时对象,确保原本的天数加上新天数后合法 想错,因为没有合法一说,多出来的天数进制!!!!!!!!!
	_day += day;

	// 多出来的天数进制!!!!!!!!!!!!!
	while (_day > GetMonthDay(_year, _month))
	{
		// 向前进一个月
		_day -= GetMonthDay(_year, _month);
		_month++;

		// 月份超出12
		if (_month > 12)
		{
			_year++;
			_month = 1;
		}
	}

	// 返回引用类型时,引用的对象必须出了作用域仍然存在!!!!!!!!!!
	return *this;
}

2.3 日期+天数

// 日期+天数,d2 = d1 + 2 -> d1.operator(2) -> d1.operator(&d1, 2)
// this指向的对象不用修改,加const
// 相当于Date operator+(const Date* const this, int day)
// 返回值不用引用,因为+计算后d1的值不变,返回值用引用只能引用出作用域还存在的对象,此处不是返回d1,而是计算后的新对象

Date Date::operator+(int day)const
{
	// 先构造临时对象,确保原本的天数加上新天数后合法
	Date tmp(*this);
	tmp._day += day;

	// 多出来的天数进制!!!!!!!!!!!!!!
	while (tmp._day > tmp.GetMonthDay(tmp._year, tmp._month))
	{
		// 向前进一个月
		tmp._day -= tmp.GetMonthDay(tmp._year, tmp._month);
		tmp._month++;

		// 月份超出12
		if (tmp._month > 12)
		{
			tmp._year++;
			tmp._month = 1;
		}
	}

	return tmp;
}

// +和+=复用时:

// 1:+复用+=:(2次拷贝构造 -> 2次拷贝构造)相对更优
// Date tmp(*this);
// tmp += day;
// return tmp;

// 2:+=复用+时:(0次拷贝构造 -> 2次拷贝构造)
// *this = *this + day
// return *this

2.4 日期-=天数

// 日期-=天数
Date& Date::operator-=(int day)
{
	// 负数也可以处理!!!!!!!!!!!!!!!!!
	if (day < 0)
	{
		return *this += (-day);
	}

	this->_day -= day;

	while (this->_day <= 0)
	{
		// 天数重置,相应月份也改变
		this->_day += this->GetMonthDay(this->_year, this->_month - 1);
		this->_month--;

		if (0 == this->_month)
		{
			this->_month = 12;
			this->_year--;
		}
	}

	return *this;
}

2.5 ++日期

// ++日期,++d1 -> d1.operator++() -> d1.operator++(&d1)
// this指向的对象修改,不加const
// 相当于Date operator++(Date* const this)
// 返回值用引用,返回值用引用只能引用出作用域还存在的对象,此处返回*this即d1

Date& Date::operator++()
{
	(*this) += 1;// 合法性在+=运算符重载中确定
	return *this;
}

2.6 日期++

// 日期++,d1++ -> d1.operator++(int) -> d1.operator++(int, &d1)
// this指向的对象修改加const
// 相当于Date operator++(int, const Date* const this)
// 返回值不用引用,返回值用引用只能引用出作用域还存在的对象,此处返回(*this+1),在+运算符重载中返回的是新对象

Date Date::operator++(int)
{
	//return ((*this) + 1);// 合法性在+运算符重载中确定 理解错,后置++是赋值原先的值,但是自身改变!!!!!!!!

	Date tmp(*this);
	*this += 1;
	return tmp;
}

2.7 日期>日期

// 日期>日期?,d1>d2 -> d1.operator>(d2) -> d1.operator>(&d1, d2)
// this指向的对象不修改加const
// 相当于bool operator>(const Date* const this, const Date& d)const,d不修改所以加const
// 返回bool值

bool Date::operator>(const Date& d)const
{
	// 已创建的对象,需经过构造函数判定日期合法,所以已存在的对象比较,日期必合法
	/*if (this->_year > d._year)
	{
		return true;
	}

	if (this->_year == d._year && this->_month > d._month)
	{
		return true;
	}

	if (this->_year == d._year && this->_month == d._month && this->_day > d._day)
	{
		return true;
	}*/

	// 可合并!!!!!!!!!!!!!!!!
	if ((_year > d._year)
		|| (_year == d._year && _month > d._month)
		|| (_year == d._year && _month == d._month && d._day > d._day))
	{
		return true;
	}

	// 上述代码执行完之后始终没有返回则返回false
	return false;

}

2.8 日期==日期

// 日期==日期?,d1==d2 -> d1.operator==(d2) -> d1.operator==(&d1, d2)
// this指向的对象不修改加const
// 相当于bool operator==(const Date* const this, const Date& d)const,d不修改所以加const
// 返回bool值

bool Date::operator==(const Date& d)const
{
	// 已创建的对象,需经过构造函数判定日期合法,所以已存在的对象比较,日期必合法
	return (this->_year == d._year && this->_month == d._month && this->_day == d._day);
}

2.9 日期>=日期

// 日期>=日期?,d1>=d2 -> d1.operator>=(d2) -> d1.operator>=(&d1, d2)
// this指向的对象不修改加const
// 相当于bool operator>=(const Date* const this, const Date& d)const,d不修改所以加const
// 返回bool值

bool Date::operator>=(const Date& d)const
{
	// 已创建的对象,需经过构造函数判定日期合法,所以已存在的对象比较,日期必合法
	return ((*this > d) || (*this == d));
}

2.10 日期!=日期

// 日期!=日期?,d1!=d2 -> d1.operator!=(d2) -> d1.operator!=(&d1, d2)
// this指向的对象不修改加const
// 相当于bool operator!=(const Date* const this, const Date& d)const,d不修改所以加const
// 返回bool值

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

2.11 日期-日期

// 日期-日期,d1-d2 -> d1.operator(d2) -> d1.operator(&d1, d2)
// this指向的对象不修改加const
// 相当于int operator-(const Date* const this, const Date& d)const,d不修改所以加const
// 返回int值

int Date::operator-(const Date& d)const// 不会!!!!!!!!!!!!!!!!!!!!
{
	// 看了解析后写:
	Date max = *this;
	Date min = d;
	int index = 1;
	
	if (d > *this)
	{
		max = d;
		min = *this;
		index = -1;
	}

	int ret = 0;
	while (max != min)
	{
		++ret;
		++min;
	}

	return ret * index;
}

2.12 流插入运算符重载(全局函数)

// 流插入操作符重载(全局函数)
std::istream& operator>>(std::istream& in, Date& d)//要改变d的成员,所有不加const
{
	// 判断日期的合法性
	if (d._year >= 1 && d._month >= 1 && d._month <= 12 && d._day >= 1 && d._day <= d.GetMonthDay(d._year, d._month))
	{
		in >> d._year >> d._month >> d._day;
		return in;
	}
	else
	{
		cout << "日期非法" << endl;
	}
}

2.13 流提取运算符重载(全局函数)

// 流提取操作符重载(全局函数)
std::ostream& operator<<(std::ostream& out, const Date& d)
{
	out << d._year << "-" << d._month << "-" << d._day << endl;

	return out;
}

总结

这里对文章进行总结:
以上就是今天总结的内容,本文包括了类与对象-日期类(c++实现),分享给大家。
真💙欢迎各位给予我更好的建议,欢迎访问!!!小编创作不易,觉得有用可以一键三连哦,感谢大家。peace
希望大家一起坚持学习,共同进步。梦想一旦被付诸行动,就会变得神圣。

欢迎各位大佬批评建议,分享更好的方法!!!🙊🙊🙊

评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值