类和对象——日期类实现

news2024/9/20 20:40:25

目录

前言:

一、构造

二、运算符重载

三、++与--

四、实现+与+= 操作

        4.1 实现+= 操作

        4..2 实现+操作

        4.3 效率分析

五、实现 - 与-= 操作符

六、日期减日期

七、流插入和流提取

八、完整代码

        Date.h

        Date.cpp


前言:

        我们之前已经学习过了类和对象,我们今天来实践应用一下,来增强感悟!

一、构造

        我们要实现日期类第一步便是对其经行构造,使其成为一个类,以下便是创建的类:

class Date
{
  public:
    Date(int year = 0, int month = 0, int day = 0);
  private:
	int _year;
	int _month;
	int _day;  
};

        日期类只需创建出年月日即可,以下是实例化,我们这次是声明和实现分开。

Date::Date(int year,int month, int day)
{
		_year = year;
		_month = month;
		_day = day;
}

        这便是日期类的创建,看着这代码,你不由陷入了深思:如果我随便输入月和日该如何处理,比如:2月31日,这不就是坑吗?咱们要防患于未然,那我们能不能写一个函数,来获取月份的天数,然后我们在进行判断,符合我们就采取,不符合就进行提示。

        说干就干,那我们该如何获取月份天数呢?我们可采取这个方法:先定义一个数组,把每个月天数放进去,二月按照28天先放,然后进行闰年判断,是闰年2月返回29,否则就按照数组中的值进行返回。

int Date::GetMonthDay(int year,int month)
{
	assert(month > 0 && month < 13);
	int _month[13] = { 0,31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };  //此处定义为13是为了方便,不用进行处理
	if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)				//闰年判断
	{
		if (month == 2)
		{
			return 29;
		}
	}
		return _month[month];
}

        那,我们日期类的创建可以做出以下的改进:

Date::Date(int year,int month, int day)
{
	if (month > 0 && month < 13
		&& (day > 0 && day <= GetMonthDay(year, month)))
	{
		_year = year;
		_month = month;
		_day = day;
	}
	else
	{
		cout << "非法坐标" << endl;
	}
}

        这下你看的顺眼多了,但还是觉得缺点什么?还没实现打印函数,那就顺手实现吧!

void Date::Print()
{
	cout << _year << "/" << _month << "/" << _day;
}

        好了,接下来实现下一个函数吧!

二、运算符重载

        运算符重载在之前文章都有介绍,这里就简单说一下:我们只需任意两个即可,其余我们都可以进行复用。实现如下:

bool Date::operator==(const Date& d)
{
	return _year == d._year
		&& _month == d._month
		&& _day == d._day;
}

bool Date::operator<(const Date& d)
{
	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;
}

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

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

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

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

        我们这里实现的是== 与 < 这两个运算符,大家可自行选择,难度不大。

三、++与--

        关于这两个运算符都有前置与后置两个用法,区别为:前置后面无参数,后置后面需加int,但这个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 *this;
}

四、实现+与+= 操作

        4.1 实现+= 操作

                大家想一想:对于+= 这个操作,大家如何实现。我们想要实现可不可以这样搞:先啥都不管先把日期加上再说,那要是超出日期怎么办?简单,把月++然后把日减去月++前的月日期,如果还不符合,循环即可。如果月份大于十二,那就月份置一,年++。这个思路应该没啥问题。那我们考虑一点:如何接受返回值?在使用该操作符时我们明白:会改变该变量本身。所以,我们直接将其本身返回即可。实现如下:

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

	}
	return *this;
}

        4..2 实现+操作

                对于+这个操作符我们是否能够可以参考以上的思路?当然可以,不过我们思考一件事:我们使用+这个操作符,它本身是不是不改变?改变的原因是不是最后的赋值?大家想清楚这个问题,想清楚了这个问题我们来想如何解决这个问题,那既然是不改变,我们能不能创建一个临时变量叫它来帮助我们,就像实现后置++、--操作符。我们的实现如下:

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 > 12)
		{
			tmp._month = 1;
			tmp._year++;
		}
	}
	return tmp;
}

        4.3 效率分析

                对于以上我们是不是可以用运算符重载来实现,那我们不禁思考:用谁来实现谁比较好?是+来复用+=,还是+=来复用+?这关乎与效率问题,大家选好心目中的队伍,我们来分析吧!

五、实现 - 与-= 操作符

        有了 + 与 += 操作符的实现,我们对于该操作符实现可以说是很简单了,所以,大家参考以下代码即可:

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

Date Date::operator-(int day)
{
	Date tmp(*this);
	tmp -= day;
	return tmp;
}

        咱们现在以是实现完毕,这时我们想一个问题:如果有人故意捣乱传的值为负数怎么办?很简单,+= 移交给 -= ,反之,亦然。咱们以-= 为例,只需加入以下代码即可:

Date& Date::operator-=(int day)
{
	if (day < 0)					//进行判断,符合条件进行复用即可
	{
		*this += day;
		return *this;
	}
	_day -= day;
	while (_day <= 0)
	{
		_month--;
		if (_month == 0)
		{
			_year--;
			_month = 12;
		}
		_day += GetMonthDay(_year, _month);
	}
	return *this;
}

六、日期减日期

        我们明白,日期加日期没啥用,但是日期减去一个日期就有用了不少,我们不禁想明白这个该如何实现:直接减去,我们啥都要考虑,闰年不润年先放一边,主要是你月份相减所得的天数是哪几个月的?这是个很复杂的问题。现提供如下思路:我们先把大的选出来,如果小的减去大的最后乘以-1即可。然后,我们一直使小的++最后等于大的即可得出。代码如下:

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

七、流插入和流提取

        对于流插入和提取我们要实现的目的是:Date为自定义类型,对于自定义类型我们只能自己实现,不能依靠别人。我们要实现插入与提取最好放在全局,不放入类中,因为this指针会替代第一个问题,放入类中会反过来使用,不符合习惯。实现如下:

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;
	return in;
} 

八、完整代码

        Date.h

#pragma once
#include <iostream>
#include <assert.h>
using namespace std;

class Date 
{

	friend ostream& operator<<(ostream& out, const Date& d);
	friend istream& operator>>(istream& in, Date& d);

public:
	Date(int year = 0, int month = 0, int day = 0);
	void Print();
	int GetMonthDay(int year, int month);

	bool operator==(const Date& d);
	bool operator!=(const Date& d);
	bool operator< (const Date& d);
	bool operator<=(const Date& d);
	bool operator> (const Date& d);
	bool operator>=(const Date& d);

	Date& operator+=(int day);
	Date operator+(int day);

	Date& operator-=(int day);

	// d1 - 100
	Date operator-(int day);

	// d1 - d2;
	int operator-(const Date& d);

	// ++d1
	Date& operator++();

	// d1++
	Date operator++(int);

	Date& operator--();

	Date operator--(int);

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

        Date.cpp

#include"Data.h"

int Date::GetMonthDay(int year,int month)
{
	assert(month > 0 && month < 13);
	int _month[13] = { 0,31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };  //此处定义为13是为了方便,不用进行处理
	if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)				//闰年判断
	{
		if (month == 2)
		{
			return 29;
		}
	}
		return _month[month];
}

Date::Date(int year,int month, int day)
{
	if (month > 0 && month < 13
		&& (day > 0 && day <= GetMonthDay(year, month)))
	{
		_year = year;
		_month = month;
		_day = day;
	}
	else
	{
		cout << "非法坐标" << endl;
	}
}

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

	}
	return *this;
}

Date Date::operator+(int day)
{
	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 > 12)
//		{
//			tmp._month = 1;
//			tmp._year++;
//		}
//	}
//	return tmp;
//}
//
//Date& Date::operator+=(int day)
//{
//	*this = *this + day;
//	return *this;
//}

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 *this;
}

Date& Date::operator-=(int day)
{
	if (day < 0)					//进行判断,符合条件进行复用即可
	{
		*this += day;
		return *this;
	}
	_day -= day;
	while (_day <= 0)
	{
		_month--;
		if (_month == 0)
		{
			_year--;
			_month = 12;
		}
		_day += GetMonthDay(_year, _month);
	}
	return *this;
}

Date Date::operator-(int day)
{
	Date tmp(*this);
	tmp -= day;
	return tmp;
}

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

void Date::Print()
{
	cout << _year << "/" << _month << "/" << _day << endl;
}

bool Date::operator==(const Date& d)
{
	return _year == d._year
		&& _month == d._month
		&& _day == d._day;
}

bool Date::operator<(const Date& d)
{
	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;
}

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

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

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

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

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;
	return in;
} 

完!

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

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

相关文章

交换机-端口安全

端口安全 1 概述 端口安全&#xff08;Port Security&#xff09;通过将接口学习到的动态MAC地址转换为安全MAC地址&#xff08;包括安全动态MAC、安全静态MAC和Sticky MAC&#xff09;&#xff0c;阻止非法用户通过本接口和交换机通信&#xff0c;从而增强设备的安全性。 2 …

力扣热题100_二叉树_94_二叉树的中序遍历

文章目录 题目链接解题思路解题代码 题目链接 94. 二叉树的中序遍历 给定一个二叉树的根节点 root &#xff0c;返回 它的 中序 遍历 。 示例 1&#xff1a; 输入&#xff1a;root [1,null,2,3] 输出&#xff1a;[1,3,2] 示例 2&#xff1a; 输入&#xff1a;root [] 输…

全面提升PDF编辑效率,2024年五大顶级PDF编辑器推荐!

在这个数字化飞速发展的时代&#xff0c;PDF文件已经成为我们日常工作和学习中不可或缺的一部分。然而&#xff0c;面对PDF文件的编辑和管理&#xff0c;许多人仍然感到困惑和无助。今天&#xff0c;就让我们一起探索几款高效、易用的PDF编辑器&#xff0c;它们将彻底改变你的工…

抖音短视频素材网站有哪些?做抖音的几个素材站分享

随着短视频平台尤其是抖音的飞速发展&#xff0c;更多的内容创作者正加入到这一潮流中&#xff0c;无论是生活分享、才艺展示还是知识传播&#xff0c;一个吸引人的视频都离不开优质的素材。本文将为追求流行的抖音视频创作者介绍几个寻找热门素材的优选平台&#xff0c;帮助您…

c语言-编译预处理

9 编译预处理 预处理命令 一、预处理命令的作用 -- 在编译之前&#xff0c;需要执行的命令 -- 编译预处理是在对源程序正式编译之前的处理&#xff0c;如inlcude先替换后计算 二、预处理命令 1、#include -- 包含包括 &#xff08;1&#xff09; #include&l…

考研数学|张宇18讲太多太难,强化要不要换武老?

面对张宇18讲的难度&#xff0c;考虑是否更换辅导资料是一个值得深思的问题。首先&#xff0c;要认识到每个人的学习风格和需求是不同的。 张宇18讲可能因其深度和广度而受到一些考生的青睐&#xff0c;但同时也可能因其难度让部分考生感到挑战重重。 在决定是否更换辅导资料…

如何优雅的使用枚举类型,可以这样做!

使用枚举有时候会给我们带来了一些困扰&#xff1a; 前端展示数据&#xff0c;需要将枚举转成用户可读的数据显示。 代码中的枚举类型要存储数据库得转成数值类型。 那么本文介绍一种自动转换方案&#xff0c;大大方便前后端使用枚举类型 我们以用户状态为例&#xff0c;用…

创建型模式(Creational Patterns)之工厂模式(Factory Pattern)之工厂方法模式(Factory Method Pattern)

1. 工厂方法模式(Factory Method Pattern) 将对象的创建延迟到子类中实现&#xff0c;每个具体产品类都有一个对应的工厂类负责创建&#xff0c;从而使得系统更加灵活。客户端可以通过调用工厂方法来创建所需的产品&#xff0c;而不必关心具体的实现细节。这种模式符合开放-封闭…

客户数据分析模型:RFM模型的深度解析与应用探索

RFM模型&#xff0c;作为客户数据分析中的经典工具&#xff0c;凭借其简单而强大的分析能力&#xff0c;被广泛应用于各行各业。本文旨在深入探讨RFM模型的核心原理、应用价值&#xff0c;并详细阐述其在2C&#xff08;面向消费者&#xff09;和2B&#xff08;面向企业&#xf…

Lumerical 光束重叠率计算

Lumerical 光束重叠率计算 引言正文不同位置处 FDE Solver 对仿真结果的影响FDE Solver 不同尺寸下的光束重叠率计算引言 在 Lumerical 光纤模式仿真 一文中我们介绍了如何进行光纤模式的仿真。本文,我们将继续使用 SMF28 来进行光束重叠率计算说明。 正文 不同位置处 FDE …

大数据技术原理-spark的安装

摘要 本实验报告详细记录了在"大数据技术原理"课程中进行的Spark安装与应用实验。实验环境包括Spark、Hadoop和Java。实验内容涵盖了Spark的安装、配置、启动&#xff0c;以及使用Spark进行基本的数据操作&#xff0c;如读取本地文件、文件内容计数、模式匹配和行数…

【未授权访问漏洞复现~~~】

一: Redis未授权访问漏洞 步骤一:进入vulhub目录使用以下命令启动靶机… 进入目录:cd /vulhub-master/redis/4-unacc 启动:docker-compose up-d 检查:docker-compose ps步骤二:在Kali上安装redis程序进行服务的链接. #安装redis apt-get install redis #redis链接 redis-cli…

【Linux进程篇】并发艺术:Linux条件变量与生产消费者模型的完美融合

W...Y的主页 &#x1f60a; 代码仓库分享&#x1f495; 前言&#xff1a;我们上篇博客中提到了线程互斥、引出了互斥锁解决了线程中的未将临界资源保护的问题。但是随之出来的问题——竞争锁是自由竞争的&#xff0c;竞争锁的能力太强的线程会导致其他线程抢不到票&#xff0…

Linux——线程互斥与同步

一、线程互斥 1.1 线程间互斥的概念 在学习管道的时候&#xff0c;管道是自带同步与互斥的。而在线程中&#xff0c;当多个线程没有加锁的情况下同时访问临界资源时会发生混乱。在举例之前&#xff0c;先了解几个概念。 临界资源&#xff1a;多个线程执行流共享的资源叫做临…

软甲测试定义和分类

软件测试定义 使用人工和自动手段来运行或测试某个系统的过程&#xff0c;其目的在于检验他是否满足规定的需求或弄清预期结果与实际结果之间的差别 软件测试目的 为了发现程序存在的代码或业务逻辑错误 – 第一优先级发现错误为了检验产品是否符合用户需求 – 跟用户要求实…

WPF学习(3)- WrapPanel控件(瀑布流布局)+DockPanel控件(停靠布局)

WrapPanel控件&#xff08;瀑布流布局&#xff09; WrapPanel控件表示将其子控件从左到右的顺序排列&#xff0c;如果第一行显示不了&#xff0c;则自动换至第二行&#xff0c;继续显示剩余的子控件。我们来看看它的结构定义&#xff1a; public class WrapPanel : Panel {pub…

【网页设计】基于HTML+CSS上海旅游网站网页作业制作

一、&#x1f468;‍&#x1f393;网站题目 旅游&#xff0c;当地特色&#xff0c;历史文化&#xff0c;特色小吃等网站的设计与制作。 二、✍️网站描述 &#x1f468;‍&#x1f393;静态网站的编写主要是用HTML DIVCSS 等来完成页面的排版设计&#x1f469;‍&#x1f39…

CSP初赛知识点讲解(一)

CSP初赛知识点讲解&#xff08;一&#xff09; 信息学竞赛哈夫曼树 哈夫曼编码冯.诺依曼理论计算机奖项例题训练&#xff08;一&#xff09;操作系统例题训练&#xff08;二&#xff09;计算机语言例题训练&#xff08;三&#xff09; 信息学竞赛 全国青少年计算机程序设计竞赛…

VINS-Fusion 多传感器全局位姿估计的一种通用优化框架

摘要 对于自动导航的机器人来说,精确的状态估计是基本问题。为了实现局部精确和全局无漂移的位姿估计,通常将具有互补属性的多个传感器进行融合。在一个小的区域内,局部传感器,如相机、IMU、Lidar等,提供了精确的位姿,而在一个大场景环境下,全局传感器,如gps、magneto…

java 变量及其常量

变量 数据类型关键字内存占用取值范围字节型byte1个字节-128 至 127 定义byte变量时超出范围,废了短整型short2个字节-32768 至 32767整型int&#xff08;默认&#xff09;4个字节-231 至 231-1 正负21个亿-2147483648——2147483647长整型long8个字节-263 至 263-1 19位数字-9…