【C++基础】实现日期类

news2024/12/28 18:18:08

在这里插入图片描述

​👻内容专栏: C/C++编程
🐨本文概括: C++实现日期类。
🐼本文作者: 阿四啊
🐸发布时间:2023.9.7

对于类的成员函数的声明和定义,我们在类和对象上讲到过,需要进行声明和定义分离。

一些需要使用的接口函数声明,我们放入到Date.h文件中
#include <iostream>
using namespace std;

class Date
{
 
public:
	//构造函数
	Date(int year = 1, int month = 1, int day = 1);

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

	//析构函数
	//~Date(); //日期类可以不写
	
	//打印日期
	void Print()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=(const Date& d);


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

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

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

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

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

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

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

private:
	int _year;
	int _month;
	int _day;
};

🤗🤗下面,我们对一些日期接口函数的实现:

实现于Date.cpp文件中

一、构造函数、拷贝构造以及日期的打印

#include "date.h"
//构造函数
Date::Date(int year, int month, int day)
{
	_year = year;
	_month = month;
	_day = day;

	//检查日期是否合法
	if (month < 1 || month > 12 || day < 1 || day > GetMonthDay(year, month))
	{
		cout << "非法日期" << endl;
		//exit(-1);
	}
}
Date::Date(const Date& d)
{
	_year = d._year;
	_month = d._month;
	_day = d._day;
}
//Date::~Date()
//{
//	cout << "~Date()" << endl;
//}
void Date::Print() const
{
	cout << _year << "年" << _month << "月" << _day << "日" << endl;
}

二、赋值运算符重载函数

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

三、运算符重载

比较运算符重载

我们写一个operator< 运算符重载函数和一个 operator== 运算符重载函数即可,其他直接复用就行。

bool Date::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;
	}
	else
	{
		return false;
	}
}
bool Date::operator==(const Date& d) const
{
	return _year == d._year && _month == d._month
		&& _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) || (*this == d);
}
bool Date::operator!=(const Date& d) const
{
	return !(*this == d);
}

日期 ± 天数、日期 - 日期

获取当前月份的天数

首先我们需要写一个获取当月的天数GetMonthDay()函数,以便于后面用日期 ± 天数运算。

//获取当月天数
int Date::GetMonthDay(int year, int month) const
{
	static int MonthDayArray[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

	//判断是否为闰年(先判断是否为2月)
	if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 4 == 0)))
	{
		return 29;
	}
 
	return MonthDayArray[month];
}

日期 += 天数 与 日期 + 天数

//日期+= 天数
Date& Date::operator+=(int day)
{
	if (day < 0)
	{
		return *this -= -day;
	}
	 
	_day += day;

	while (_day > GetMonthDay(_year, _month))
	{
		//月进位
		_day -= GetMonthDay(_year, _month);
		_month++;
		if (_month == 13)
		{
			_year++;
			_month = 1;
		}
	}

	return *this;
}
//日期 + 天数
Date Date::operator+(int day) const
{
	Date tmp(*this);
	tmp += day;
	return tmp;
}
日期+ 天数
//Date Date::operator+(int day)
//{
//	Date tmp(*this);
//	tmp._day += day;
//
//	while (tmp._day > GetMonthDay(tmp._year, tmp._month))
//	{
//		//月进位
//		tmp._day -= GetMonthDay(tmp._year, tmp._month);
//		tmp._month++;
//		if (tmp._month == 13)
//		{
//			tmp._year++;
//			tmp._month = 1;
//		}
//	}
//
//	return tmp;
//}
//
日期 += 天数
//Date& Date::operator+=(int day)
//{
//	*this = *this + day;
//	return *this;
//}

在这里插入图片描述

日期 -= 天数 与 日期 - 天数

我们知道了先写operator+=,再写operator+直接复用即可这种方法更优,所以我们日期减去天数也是实现operator-=,再实现operator-

//日期 -= 天数
Date& Date::operator-=(int day)
{
	if (day < 0)
	{
		return *this += -day;
	}

	_day -= day;
	while (_day <= 0)
	{
		_month--;
		if (_month == 0)
		{
			_year--;
			_month = 12;
		}
		_day += GetMonthDay(_year, _month);
	}
	return *this;
}

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

	return tmp;
}

自增 和 自减 重载

C++规定:前置++和后置++都是一元运算符,为了让前置++与后置++形成能正确重载,后置++重载时多增加了一个int类型的参数,与前置++构成函数重载,以区分前置++

//前置++
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;
}

日期 - 日期

// d1 - d2
int Date::operator-(const Date& d) const
{
	//默认认为左边日期大
	Date max = *this;
	Date min = d;

	int flag = 1;//为1返回正数,-1返回负数
	int count = 0;//统计天数

	//不成立则交换
	if (*this < d)
	{
		max = d;
		min = *this;
		flag = -1;
	}

	//while(min < max)
	while (min != max)
	{
		min++;
		count++;
	}
	
	return count * flag;
}

四、全局函数实现流插入流提取

date.h 流插入流提取重载函数的声明
/*不能重载成成员函数,否则会导致参数不匹配,因为this指针永远占据第一个位置,无法进行流插入提取操作。*/
//流插入
ostream& operator<<(ostream& out, const Date& d);
//流提取
istream& operator>>(istream& in, Date& d);

如果重载成成员函数,那么成员函数的第一个参数永远是隐藏的this指针,成员函数中只能利用out << _year << _month << _day的顺序,但是在调用时, (d1为日期类对象)d1 << cout,只能这么写,虽然可以,但是很别扭,不符合使用习惯和价值。所以我们需要实现成全局函数才可以。
在这里插入图片描述
但是写成全局函数会访问类的成员变量,我们可以利用友元或者将成员变量封装成成员函数解决。

date.cpp 流插入流提取重载函数的实现
/*不能重载成成员函数,否则会导致参数匹配,因为this指针永远占据第一个位置,无法进行流插入提取操作。*/
//涉及访问私有成员变量可以利用友元,或者将成员变量封装成Get成员函数
//流插入
ostream& operator<<(ostream& out, const Date& d)
{
	out << d._year << "年" << d._month << "月" << d._day << "日" << endl;
	return out;
}
//流提取
istream& operator>>(istream& in, Date& d)
{
	in >> d._year >> d._month >> d._day;
}

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

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

相关文章

mac 查看端口占用

sudo lsof -i tcp:port # 示例 sudo lsof -i tcp:8080 杀死进程 sudo kill -9 PID # 示例 sudo kill -9 8080

“搞事情”?OpenAl将于11月召开其首届开发者大会

摘要&#xff1a;OpenAI也要召开它的第一届开发者大会了。这次活动&#xff0c;或许标志着OpenAI向其下一阶段的商业开发迈出了关键一步。 昨天&#xff0c;OpenAI宣布将于11月6日举办其首次开发者大会。在这场名为“OpenAI DevDay”的活动中&#xff0c;OpenAI的技术人员将进行…

欧科云链与HashKey Exchange达成合作,助力香港虚拟资产合规化

继8月10日 欧科云链 与 华为云 达成合作之后&#xff0c; 今天&#xff0c;欧科云链 又与 Hashkey Exchange 共同宣布正式达成合作&#xff01; 这次与Hashkey达成合作&#xff0c;双方又将在Web3行业中谱写怎样的故事&#xff1f; 9月6日&#xff0c;欧科云链控股有限公司&…

2023 年高教社杯全国大学生数学建模竞赛题目 C 题 蔬菜类商品的自动定价与补货决策

C 题 蔬菜类商品的自动定价与补货决策 在生鲜商超中&#xff0c;一般蔬菜类商品的保鲜期都比较短&#xff0c;且品相随销售时间的增加而变差&#xff0c; 大部分品种如当日未售出&#xff0c;隔日就无法再售。因此&#xff0c;商超通常会根据各商品的历史销售和需求情况每天进…

生物通路数据库收录1600+整合的经典通路

生物通路数据库为科学家提供了关于生物通路的大量信息和资源&#xff0c;特别是在数据整合、信息检索、数据可视化分析、数据交互、生物学研究等方面&#xff0c;积极推动了生物学研究和科学的发展。 世界各地正在创建各种类型的通路数据库&#xff0c;每个数据库都反映了其创…

快递批量查询高手必备的实用工具

在网购日益普及的今天&#xff0c;我们经常需要查询快递的物流信息。但是&#xff0c;传统的查询方式一个一个地输入快递单号&#xff0c;不仅费时费力&#xff0c;还容易出错。有没有一种方法可以批量查询多个快递单号呢&#xff1f;答案是肯定的&#xff0c;今天我们就来介绍…

2140. 解决智力问题;1401. 圆和矩形是否有重叠;901. 股票价格跨度

2140. 解决智力问题 核心思想:动态规划。dp[i]表示解决i-n-1的问题所能获得的最高分数&#xff0c;注意需要倒叙遍历&#xff0c;因为i的状态由后面的状态转移过来的。 1401. 圆和矩形是否有重叠 核心思想&#xff1a;分情况讨论&#xff0c;圆心情况。借用别人一张图说明。 …

JWT-Token升级方案

1. 介绍 JWT是JSON Web Token的缩写&#xff0c;即JSON Web令牌&#xff0c;是一种自包含令牌。 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息&#xff0c;以便于从资源服务器获取资…

ATFX汇市:美联储褐皮书透露就业市场新动向,美元指数中期多头趋势延续

ATFX汇市&#xff1a;今日2:00&#xff0c;美联储发布褐皮书&#xff0c;关于就业市场&#xff0c;其中提到&#xff1a;全国就业增长乏力&#xff0c;大多数地区的劳动力成本压力增长加剧&#xff0c;企业预计工资增长将在短期内普遍放缓。从7月、8月的非农就业报告当中&#…

数据结构和算法(2):向量

抽象数据类型 数组到向量 C/C 中&#xff0c;数组A[]中的元素与[0,n)内的编号一一对应&#xff0c;A[0],A[1],...,A[n-1]&#xff1b;反之&#xff0c;每个元素均由&#xff08;非负&#xff09;编号唯一指代&#xff0c;并可直接访问A[i] 的物理地址 Ai s&#xff0c;s 为单…

vue-elementPlus自动按需导入和主题定制

elementPlus自动按需导入 装包 -> 配置 1. 装包&#xff08;主包和两个插件包&#xff09; $ npm install element-plus --save npm install -D unplugin-vue-components unplugin-auto-import 2. 配置 在vite.config.js文件中配置&#xff0c;配置完重启&#xff08;n…

SM5202 是一款完整的采用恒定电流/恒定电压的单节锂电池线性充电器

简介&#xff1a; SM5202 是一款完整的采用恒定电流/恒定电压的单节锂电池线性充电器&#xff0c;并带有锂电池正负极反接保护功能&#xff0c;可以保护芯片和用户安全。由于采用了内部 PMOSFET 架构&#xff0c;加上防倒充电路&#xff0c;所以不需要外部检测电阻和隔离二极管…

Java之包装类的算法小题的练习

算法小题 练习一&#xff1a; 需求&#xff1a; 键盘录入一些1~10日之间的整数&#xff0c;并添加到集合中。直到集合中所有数据和超过200为止。 代码示例&#xff1a; public class Test1 {public static void main(String[] args) {/*键盘录入一些1~10日之间的整数&…

产业大数据应用:洞察区域产业实况,把握区域经济脉搏

​ 随着新一代信息技术的崛起&#xff0c;我们进入了大数据时代。在这个时代&#xff0c;数据作为基本生产要素不仅改变着我们的日常生活&#xff0c;更是在区域产业经济发展中扮演着重要角色&#xff0c;它赋予了政府、企业和投资者敏锐的洞察力。 一、摸清区域经济现状 基于…

智慧公厕如何实现系统管理、运行数据、业务流程的高度耦合

随着城市发展和人口增长&#xff0c;公共厕所成为城市更新与发展的重要环节。然而&#xff0c;传统的公共厕所管理方式面临诸多问题&#xff0c;如运营成本高、环境污染、人员管理等。为了解决这些问题&#xff0c;智慧公厕应运而生。智慧公厕是指利用现代科技手段&#xff0c;…

RPC接口测试-两种方法(Jmeter和代码)

相信很多同学在测试RPC接口时会遇到很多困难&#xff0c;博主前段时间在测试时也一样&#xff0c;算是提前踩坑啦&#xff0c;下面就来介绍一下测试RPC接口的方法 1.什么是RPC接口 RPC&#xff08;Remote Procedure Call&#xff09;是一种通信协议和模式&#xff0c;用于在分…

Linux之权限

目录 一、shell运行原理 二、权限 1、对人操作 2、对角色和文件操作 修改权限&#xff08;改属性&#xff09;&#xff1a; ①ugo- ②二进制数的表示 修改权限&#xff08;改人&#xff09;&#xff1a; 三、权限的相关问题 1、目录的权限 2、umask 3、粘滞位 一、s…

一百七十一、Flume——Flume1.9.0单机版安装(亲测有效)

一、目的 以防万一&#xff0c;为了避免kettle从Kafka同步数据到HDFS有问题&#xff0c;因此也测试了用Flume去采集Kafka中的数据然后同步到HDFS&#xff0c;算是一套备用方案 二、安装包版本 &#xff08;一&#xff09;Hadoop版本 hadoop-3.1.3.tar.gz &#xff08;二&a…

JS中执行上下文和执行栈是什么?

一&#xff1a;执行上下文 执行上下文是一种对js执行代码的环境的一种抽象&#xff0c;只要js在执行中&#xff0c;那它一定是运行在执行上下文中 执行上下文的类型 全局执行上下文&#xff1a;全局执行上下文是在程序启动时创建的&#xff0c;它包含全局范围定义的变量和函数…