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

相关推荐
2301_7766816524 分钟前
【用「概率思维」重新理解生活】
开发语言·人工智能·自然语言处理
熊大如如1 小时前
Java 反射
java·开发语言
ll7788111 小时前
C++学习之路,从0到精通的征途:继承
开发语言·数据结构·c++·学习·算法
我不想当小卡拉米2 小时前
【Linux】操作系统入门:冯诺依曼体系结构
linux·开发语言·网络·c++
teacher伟大光荣且正确2 小时前
Qt Creator 配置 Android 编译环境
android·开发语言·qt
炎芯随笔2 小时前
【C++】【设计模式】生产者-消费者模型
开发语言·c++·设计模式
乌鸦9442 小时前
《类和对象(下)》
开发语言·c++·类和对象+
炒空心菜菜2 小时前
SparkSQL 连接 MySQL 并添加新数据:实战指南
大数据·开发语言·数据库·后端·mysql·spark
多多*3 小时前
算法竞赛相关 Java 二分模版
java·开发语言·数据结构·数据库·sql·算法·oracle
逐光沧海3 小时前
数据结构基础--蓝桥杯备考
数据结构·c++·算法·蓝桥杯