9.C++面向对象6(实现一个较为完善的日期类)

⭐本篇重点:const成员变量和函数,取地址重载

⭐本篇代码:c++学习/02.c++面向对象-中/2.实现完善的日期类 · 橘子真甜/c++-learning-of-yzc - 码云 - 开源中国 (gitee.com)

目录

[一. 日期类分析](#一. 日期类分析)

[二. 代码实现](#二. 代码实现)

[2.1 构造函数](#2.1 构造函数)

[2.2 拷贝构造](#2.2 拷贝构造)

[2.3 析构函数](#2.3 析构函数)

[2.4 赋值运算符重载](#2.4 赋值运算符重载)

[2.5 比较运算重载](#2.5 比较运算重载)

[2.6 加减法运算符重载](#2.6 加减法运算符重载)

[2.7 自增自减运算符重载](#2.7 自增自减运算符重载)

一. 日期类分析

我们想要实现一个完善的日期类,首先要有基本的构造函数,析构函数,拷贝构造函数,赋值运算符重载。

我们在日常生活中对日期的操作有,一个日期去加减某个天数获得另一个日期,比较两个日期(大于,小于,等于)。没有乘法除法(对于日期来说没有意义)

根据分析,我们能够很快写出成员函数和成员变量的基本框架。

cpp 复制代码
class Date
{
public:
	//构造函数
	Date(int year = 0, int month = 0, int day = 0)
	{}

	//析构函数
	~Date()
	{}

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

	//赋值运算符重载
	Date& 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
	{}

	//大于等于
	bool operator>=(const Date& d)const
	{}

	//加减操作

	//加等
	Date& operator+=(int day)
	{}

	//加
	Date& operator+(int day)
	{}

	//减等
	Date& operator-=(int day)
	{}

	//减
	Date& operator-(int day)
	{}

	//前置++,++d1
	Date& operator++()
	{}

	//后置++,d1++,后置++我们在函数参数中用一个int进行标识,这是c++的约定
	Date& operator++(int)
	{}

	//前置--,--d1
	Date& operator--()
	{}

	//后置--,d1--
	Date& operator--(int)
	{}
private:
	int _year;
	int _month;
	int _day;
};

二. 代码实现

2.1 构造函数

我们知道一年有12个月,每个月都有自己的天数,那么用户输入的年,月,日就一定要合法。如果输入不合法就向用户显示报错。

年份和月份都很好判断,年份:不是负数就行。月份:1<= m <=12。

比较难判断的是日期,每月的天数不一样且有闰年存在,所以我们需要定义一个函数来获取某年某月的天数范围。

该函数代码如下:

cpp 复制代码
	//获取某年某月的最大天数
    int GetMonthDay(const int& year, const int& month)
	{
		static int MonthDays[13] = { 0,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;
		}

		return MonthDays[month];
	}

因此构造函数如下

cpp 复制代码
	//构造函数
	Date(int year = 0, int month = 0, int day = 0)
	{
		if (year >= 0 && month >= 0 && month <= 12 && day <= GetMonthDay(year, month))
		{
			_year = year;
			_month = month;
			_day = day;
		}
		else
		{
			cout << "输入非法日期" << endl;
			_year = _month = _day = -999999;
		}
	}

2.2 拷贝构造

cpp 复制代码
	//拷贝构造函数
	Date(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}

2.3 析构函数

无动态分配内存,不需要释放空间

cpp 复制代码
//析构函数
	~Date()
	{}

2.4 赋值运算符重载

为了支持 d1 = d2 = d3这种操作,我们需要使用引用返回(见赋值运算符重载

cpp 复制代码
	//赋值运算符重载
	Date& operator=(const Date& d)
	{
		if (this != &d)//this和d不同的情况下才能赋值
		{
			_year = d._year;
			_month = d._month;
			_day = d._day;
		}

		return *this;	//引用返回不能返回临时变量
	}

2.5 比较运算重载

小于

年份小一定小,年份相等,月份小一定小,年月相等,日小一定小

cpp 复制代码
	//小于,定义为const函数
	bool operator<(const Date& d)const
	{
		if (_year < d._year)
			return true;
		else if (_year == d._year && _month < d._month)
			return true;
		else if (_year == d._year && _month == d._month && _day < d._day)
			return true;
		return false;
	}

等于

cpp 复制代码
	//等于
	bool operator==(const Date& d)const
	{
		return _year == d._year && _month == d._month && _day == d._day;
	}

有了小于运算符重载和等于运算符重载,我们可以调用这个函数完成其他比较(函数复用)

小于等于

cpp 复制代码
	//小于等于
	bool operator<=(const Date& d)const
	{
		return *this < d || *this == d;
	}

大于

cpp 复制代码
	//大于
	bool operator>(const Date& d)const
	{
		return !(*this <= d);
	}

大于等于

cpp 复制代码
	//大于等于
	bool operator>=(const Date& d)const
	{
		return !(*this < d);
	}

不等于

cpp 复制代码
	//不等于
	bool operator!=(const Date& d)const
	{
		return !(*this == d);
	}

2.6 加减法运算符重载

加减法是用于两个日期相加吗??

2024/11/12 + 2024/11/13 没有意义所以我们实现的加减法都是一个日期去加减一个天数

如: 2024/11/12 + 1

我们首先实现+=这个操作符和-=

我们直接将合法day加入到这个日期的_day中,然后循环判断其值是否大于这年这月的天数,如果大于让其减去这个月的天数然后让_month++,如果_month大于12说明要进位年,_year++,_month-=12即可

+=

cpp 复制代码
	//加等
	Date& operator+=(int day)
	{
		if (day < 0)
		{
			day -= (-1 * day);
		}
		else
		{
			_day += day;
			while (_day > GetMonthDay(_year, _month))
			{
				day -= GetMonthDay(_year, _month);
				_month++;

				if (_month >= 13)
				{
					_month -= 12;
					_year++;
				}
			}
		}
		return *this;
	}

-=也是类似的思路

cpp 复制代码
//减等
	Date& operator-=(int day)
	{
		if (day > 0)
		{
			day -= (-1 * day);
		}
		else
		{
			_day -= day;
			while (_day <= 0)
			{
				_month--;

				if (_month == 0)
				{
					_year--;//月份为0,说明年份要-1
					_month = 12;//月份回到早一年的12
				}
				_day += GetMonthDay(_year, _month);
			}
		}
		return *this;
	}

实现了+=和-=我们就能够用这两个重载去实现+和- (实现对函数的复用)

注意不要使用引用返回!

cpp 复制代码
	//加,这里不是使用引用返回是因为 d = d1+day 返回值应该是一个新创造的日期
	//如果使用引用返回,我们就会返回一个临时变量
	Date operator+(int day)
	{
		Date ret = *this;
		ret += day; //本质是 ret.operator+(day);
		return ret;
	}
cpp 复制代码
	//减
	Date operator-(int day)
	{
		Date ret = *this;
		ret -= 1;
		return ret;
	}

2.7 自增自减运算符重载

d++

cpp 复制代码
	//前置++,++d1,可以使用引用返回,减少拷贝
	Date& operator++()
	{
		*this += 1; //调用+=进行复用
		return *this;
	}

++d

cpp 复制代码
	//后置++,d1++,后置++我们在函数参数中用一个int进行标识,这是c++的约定
	Date operator++(int)
	{
		//后置++我们返回的是加1之前的值
		//所以我们不能使用引用返回
		Date tmp = *this;//保留加之前的值
		*this += 1;
		return tmp;//返回加之前的值
	}

--d

cpp 复制代码
	//前置--,--d1
	Date& operator--()
	{
		*this -= 1;
		return *this;
	}

d--

cpp 复制代码
	//后置--,d1--
	Date operator--(int)
	{
		Date tmp = *this;//保留加之前的值
		*this -= 1;
		return tmp;//返回加之前的值
	}

至此一个完善的日期类就实现了,完整代码见Gitee

相关推荐
羊小猪~~27 分钟前
前端入门一之ES6--递归、浅拷贝与深拷贝、正则表达式、es6、解构赋值、箭头函数、剩余参数、String、Set
开发语言·前端·javascript·css·正则表达式·html·es6
code_shenbing1 小时前
跨平台WPF框架Avalonia教程 十四
开发语言·ui·c#·wpf
932我2 小时前
C++中的组合模式
开发语言·c++·组合模式
MrJson-架构师2 小时前
java 操作Mongodb
java·开发语言·mongodb
红中马喽2 小时前
JS学习日记(jQuery库)
开发语言·javascript·笔记·学习·jquery
这将会是一个好名字2 小时前
Mac上详细配置java开发环境和软件(更新中)
java·开发语言·macos
吃榴莲的小鳄鱼2 小时前
深挖C++赋值
java·开发语言·c++
0x派大星2 小时前
【Golang】——Gin 框架中的模板渲染详解
开发语言·后端·golang·go·gin
q567315233 小时前
Django 外键引用另一个表中的多个字段
开发语言·数据库·后端·django·sqlite