日期类的模拟实现

news2024/11/26 18:24:20

1.定义一个日期类

有关类的定义,首先是需要声明共有类和私有类的成员函数和成员变量。

这里我分了三个文件写,分别有Date.h,Date.cpp,test.cpp

using namespace std;
class Date
{
private:
	int _year;
	int _month;
	int _day;

public:
	Date(int year, int month, int day);
	void Print()
	{
		cout << _year << "/" << _month << "/" << _day << endl;
	}
};

在代码中,声明了一个Date的构造函数,但是我把Date的定义放到了Date.cpp里面,也就是说,这里的声明和定义分离了。为什么要这样搞?这是由于如果不进行声明与定义的分离的话,当Date.cpp和test.cpp两个文件共同包含了Date.h的时候,在编译后进行链接的时候,由于会出现两个Date的构造函数,会被编译器认为是一种重定义的函数,会出现链接错误。因此这边就把他们的声明和定义分离了。

那为什么声明和定义分离就不会有链接错误的情况出现呢?这就得好好说道说道什么是声明,什么是定义了。

在以往中,我们会经常喜欢把写一个int add(int x , int y);说成是函数的定义,其实这种说法是不正确的,在C++中,这仅仅是函数的声明,声明是不带有任何性质的,仅仅是让编译器看一眼,知道有这种东西的存在。就好比,我口头答应了要借给你100块钱,但我还没有给你100块钱,这就是声明。那什么是定义?定义就是写好了这个函数实现的方法。还是以上面的int add(int x , int y);为例子,我仅仅是把函数名写出来的时候他就是声明,但是我把他的实现方法写出来呢?

int add(int x ,int y)

{

        return x + y;

}

这种函数实现的过程就叫做定义。在这种情况下,函数就有了他自己的实际的意义。

2.对运算符进行重载

在实现日期类中,我们会涉及到日期的比较,和一些计算。

在进行日期类加减的时候,为了方便使用,会对运算符进行重载。

1.重载<号

那首先为了后续代码的方便,先重定义一下小于号。

bool Date:: operator<(const Date& date)
{
	if (this->_year < date._year)
	{
		return true;
	}
	else if (this->_year == date._year)
	{
		if (this->_month < date._month)
		{
			return true;
		}
		else if (this->_month == date._month)
		{
			if (this->_month < date._day)
			{
				return true;
			}
		}
	}
	return false;
}

可以看到,我在传参的时候,传了一个const Date& date这样的一个值。那为什么要写成这样?

这就涉及到了拷贝构造函数的调用。其实这中就是传一个自定义类型的参数,传引用传参和传值传参有什么区别吗?

在C++中,对于自定义类型的传参分为两种类型,一种是传值传参,一种是传引用传参。

传值传参是把自定义类型的值传到函数体里面,函数体并不是直接对他进行操作,而是首先把传过来的自定义类型进行一个拷贝,创建副本,然后再对副本进行操作,这样的操作方式是不改变参数本身的。

而传引用传参的话,就直接对传过来的参数进行操作,是会改变参数本身,就类似于之前的Swap函数的参数,参数是否是指针类型,如果是,那么就可以直接交换,如果不是,那就只能是在哪个函数域里面进行交换,出了函数域,就不会进行交换。

对于该函数的逻辑,这边再简单的说一下。首先是明确是谁在跟谁比较,如果我创建一个类是d1,另一个日期类是d2,d1<d2,这样的表达式。那么就是d1与d2在比较,而d1在函数中,他的值就存在于函数所隐含的this指针。我们传过去的d2,就是写进待传的参数里面。

2.重载>=,==,<=等运算符

前面的小于号我们已经重载好了,这就打下了一个非常良好的基础,我们甚至可以利用<号来进行接下来的符号重载。

既然是首先重载>=,那么我们不妨直接对<的逻辑进行取反不就可以了吗。

bool Date:: operator>=(const Date& date)
{
	return (*this < date);
}

其它的运算符重载也是以此类推,虽然说看起来重载了这么多,实则能用上的不过就是>,<,==这三个符号,其它的不过是为这三个符号铺路。

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

bool Date::operator==(const Date& date)
{
	return this->_year == date._year && this->_month == date._month && this->_day == date._day;
}

bool Date::operator<=(const Date& date)
{
	return (*this < date) || (*this == date);
}

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

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

 3.对+=,+,-=,-,++运算符进行重载

首先对+=,+号进行重载。目的是用当前的日期加上天数,最后输出加上天数后的日期。

Date& Date:: operator+=(int day)
{
	this->_day += day;
	while(this->_day > GetMonthDay(this->_year,this-> _month))
	{
		this->_day -= GetMonthDay(this->_year, this->_month);
		this->_month++;
		if (this->_month > 12)
		{
			this->_year++;
			this->_month = 1;
		}
	}
	return *this;
}

Date Date:: operator+(int day)
{
	Date temp = *this;
	temp += day;
	return temp;
}

这个重载+=代码的整体思路就是,一上来就先把日期加起来,如果加起来的日期超过当前日期的月份(比如在这里计算的是2024年1月1日+100天,如果加起来的天数超过1月份的天数),那么首先就把总天数-当前月份的最大天数,其次月份进行++,由于判断当前月份的天数比较复杂,且2月份又得区分当前年份是否是闰年,因此写了个GetMonthDay函数,这个稍后会解释。接着上面,当月份++后,如果月份>12,则年就++,把月份设置成1。

而在重载运算符+号的时候,可以创建一个空类,然后对这个空类进行操作。

接下来是对-=和-进行重载。

在重载-的时候,我发现我在这里想实现的是日期减去天数,但如果重载的时候使用了-号的话,那么后面的日期-日期就会冲突,因此就重载/来实现日期-天数,至于-号就用来实现日期-日期吧。

Date & Date:: operator-=(int day)
{
	this->_day -= day;
	while (this->_day <= 0)
	{
		this->_month--;
		if (this->_month <= 0)
		{
			this->_year--;
			this->_month = 12;
		}
		this->_day += GetMonthDay(this->_year, this->_month);
	}
	return *this;
}
Date Date:: operator/(int day)
{
	Date temp = *this;
	*this -= day;
	return temp;
}

int Date:: operator-(const Date& date)
{
	Date max = *this;
	Date min = date;
	if (*this < date)
	{
		max = date;
		min = *this;
	}
	int n = 0;
	while (min != max)
	{
		min++;
		n++;
	}
	return n;
}

前两个的思路都挺简单的,都是跟+=类似。我只最后说说最后的那个代码的思路吧。

首先,这个思路虽然方便,但是造成了较多的损耗。

先定义max和min,然后进行比较,如果最大值和最小值不匹配则max和min进行交换。

然后,让min一直进行自加操作,不断向着max逼近,创建一个count变量来记录,miin自加多少,count就加多少。最后返回的count就是两个日期类之间相差的天数。

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

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

相关文章

IF67负载的纳米纤维膜材料

IF67负载的纳米纤维膜材料是一种结合了ZIF67&#xff08;一种沸石咪唑酯骨架结构材料&#xff09;和纳米纤维膜的材料。这种材料的制备方法通常涉及以下步骤&#xff1a; 制备含有ZIF67纳米晶体的纺丝液。 将该纺丝液与另一纺丝液&#xff08;如聚乙烯醇缩丁醛或聚氨酯的纺丝液…

firebase:一款功能强大的Firebase数据库安全漏洞与错误配置检测工具

关于firebase firebase是一款针对Firebase数据库的安全工具&#xff0c;该工具基于Python 3开发&#xff0c;可以帮助广大研究人员针对目标Firebase数据库执行安全漏洞扫描、漏洞测试和错误配置检测等任务。 该工具专为红队研究人员设计&#xff0c;请在获得授权许可后再进行安…

Science Advances|用于非侵入性表型分析的全有机透明植物电子皮肤(植物电子皮肤/柔性电子)

新加坡国立大学 Chengkuo Lee和Eunyoung Chae团队,在期刊《Science Advances》上发布了一篇题为“All-organic transparent plant e-skin for noninvasive phenotyping”的论文。论文内容如下: 一、 摘要 植物生理的实时原位监测是建立精准农业表型平台的关键。此监测的一项…

CSS优惠券、卡券样式绘制

实现左右凹陷中间有虚线效果 效果图 实现思路 从效果图可以看到这个优惠券是左右两边凹陷&#xff0c;中间还有一条虚线&#xff0c;为了封装后插槽使用方便&#xff0c;把优惠券以虚线为准分了两部分。这样布局的好处是上部分内容和下部分都可以自定义&#xff0c;不受内容限…

cmake的使用方法: 单个源文件的编译

一. 简介 经过前一篇文章的学习&#xff0c;针对不同平台下编译 .c工程时&#xff0c;为了不用针对不同平台编写&#xff08;不同标准&#xff0c;不同规范&#xff09;Makefile文件&#xff0c;提出了 cmake工具&#xff0c;cmake可以解决跨平台编译的问题。 cmake 就是针对…

JAVA面试题---WEB部分

网络通讯 TCP与UDP TCP(Transmission Control Protocol 传输控制协议)是一种面向连接(连接导向)的、 可靠的、 基于 IP 的传输层协议。 UDP 是 User Datagram Protocol 的简称&#xff0c;中文名是用户数据报协议&#xff0c;是 OSI 参考模 型中的传输层协议&#xff0c;它是…

基于光伏电站真实数据集的深度学习预测模型(Python代码,深度学习五个模型)

效果视频链接&#xff1a;基于深度学习光伏预测系统&#xff08;五个模型&#xff09;_哔哩哔哩_bilibili 界面设计 注册界面 登录界面 主界面 展示界面 1.数据集来源 The SOLETE dataset 这里分别保存了不同间隔采样时间表格 1min是以1min 间隔采集的数据集 数据集截图&…

分享自己一篇在亚马逊云科技AWS官网发的Blog技术文章

小李哥在亚马逊AWS官网&#xff0c;作为第一作者发了自己的第一篇AWS Blog文章&#xff0c;也是自己今年在AWS官网的第11篇文章。文章主要内容是描述为出海的金融企业&#xff0c;搭建满足PCI-DSS合规、FIPS 140-2 Level 3安全标准的传输中数据加密云端方案&#xff0c;主要用于…

云服务器平台Featurize--基本使用步骤与使用感受

基本介绍 图1 网址&#xff1a;Featurize 可租用实例的显示界面如图所示。 图2 在简单的注册、登录、充值之后就可以对想要的实例直接进行租赁了。 关于实例&#xff0c;这里我的理解是已经配置好一定环境的服务器。 图3 使用感受 总结一下&#xff0c;Featurize上云服务器的…

【经典算法】LeetCode112. 路径总和(Java/C/Python3/Go实现含注释说明,Easy)

作者主页&#xff1a; &#x1f517;进朱者赤的博客 精选专栏&#xff1a;&#x1f517;经典算法 作者简介&#xff1a;阿里非典型程序员一枚 &#xff0c;记录在大厂的打怪升级之路。 一起学习Java、大数据、数据结构算法&#xff08;公众号同名&#xff09; ❤️觉得文章还…

Agent AI智能体:如何借助机器学习引领科技新潮流

文章目录 &#x1f4d1;前言一、Agent AI智能体的基本概念二、Agent AI智能体的技术进步2.1 机器学习技术2.2 自适应技术2.3 分布式计算与云计算 三、Agent AI智能体的知识积累3.1 知识图谱3.2 迁移学习 四、Agent AI智能体的挑战与机遇4.1 挑战4.2 机遇 小结 &#x1f4d1;前言…

004 秒杀下单

文章目录 超卖问题方案一方案二方案三aop锁(单机锁)aop锁(单机锁)pom.xmlLockAspect.javaServiceLock.java 分布式锁Mysql分布式锁Redis分布式锁ServiceRedisLock.javaLockRedisAspect.java 下单性能优化数据一致性解决一致性问题异步同步库存 秒杀下单业务步骤: 1.数据校验(身…

DS:顺序表、单链表的相关OJ题训练

欢迎各位来到 Harper.Lee 的学习小世界&#xff01; 博主主页传送门&#xff1a;Harper.Lee的博客主页 想要一起进步的uu可以来后台找我交流哦&#xff01; 在DS&#xff1a;单链表的实现 和 DS&#xff1a;顺序表的实现这两篇文章中&#xff0c;我详细介绍了顺序表和单链表的…

Unity SteamVR入门

概述 VR项目现在在当前已经是非常热门的技术&#xff0c;可以给玩家身临其境的感觉&#xff0c;接下来让我们学习这部分的内容吧&#xff01; SteamVR Input SteamVR绑定流程&#xff0c;在Windows窗口的点击SteamVR-input&#xff0c;图1&#xff0c;在这里可以选择你需要绑定…

Photoshop前言

Photoshop前言 分辨率图像格式工具界面组件 分辨率 分辨率是指单位长度内包含的像素点的数量&#xff0c;其单位通常为像素/英寸&#xff08;ppi&#xff09;&#xff0c;300ppi表示每英寸包含300个像素点。对于1英寸1英寸大小的图像&#xff0c;若分辨率为72ppi&#xff0c;则…

Unity MeshRenderer 入门

概述 在项目制作过程中&#xff0c;肯定缺少不了模型的使用&#xff0c;那就一定接触过MeshRenderer&#xff0c;也许还有你不理解的地方&#xff0c;接下来让我们来学习一下这部分的内容吧。 Mesh Filter&#xff08;网格过滤器&#xff09; Mesh:提供一个网格的参考&#xf…

# notepad++ 编辑器英文版,如何打开自动换行

notepad 编辑器英文版&#xff0c;如何打开自动换行 在Notepad中&#xff0c;如果你想要开启自动换行功能&#xff0c;可以按照以下步骤操作&#xff1a; 1、打开 Notepad 编辑器。 1.1. 依次点击菜单栏中的【视图】&#xff0c;英文版对应【View】。1.2. 在【视图】下拉菜单…

Integer中的缓存机制

先看一个示例&#xff1a; public static void main(String[] args) {Integer a127;Integer b127;System.out.println(ab);Integer c128;Integer d128;System.out.println(cd);} 输出&#xff1a; true false 为什么明明都是同一个数字进行比较&#xff0c;当数字等于127的…

串口单线半双工转换电路

用来把单线半双工模式的串口转换成双线&#xff0c;然后才能连接到普通的双线USB 串口模块&#xff0c;比如CH340 之类的。电路设计来自大佬的博客&#xff1a;AVR half-duplex software UART supporting single pin operation。他在Arduino 上用软件模拟串口功能&#xff0c;利…

【火猫DOTA2】电竞世界杯DOTA2项目将在7月份的前三周举办

1、电竞世界杯将于今年7月3日至8月25日在沙特利雅得举办。近日主办方公布了各个项目的举办时间,其中DOTA2项目将在7月份的前三周举办。转载:火猫TV资讯https://www.huomaotv.com/ 目前Falcons、XG、GG和Liquid这五支赢得了足够EPT积分的队伍已经确定直邀沙特。剩下的三个名额还…