【C++】-类和对象之日期类的具体实现(中)

news2024/11/20 3:27:00

💖作者:小树苗渴望变成参天大树
❤️‍🩹作者宣言:认真写好每一篇博客
💨作者gitee:gitee
💞作者专栏:C语言,数据结构初阶,Linux,C++
在这里插入图片描述
如 果 你 喜 欢 作 者 的 文 章 ,就 给 作 者 点 点 关 注 吧!

文章目录

  • 前言
  • 总结


前言

今天来写一篇关于完善日期类的博客,把之前学到知识给运用起来,最后在把类和对象中篇收个尾,博客就开始进入类和对象下篇的讲解了,那我们废话不多说,开始进入正文


对于日期类,我们需要写多文件,将声明和定义分离
在这里插入图片描述
对于日期类我们有三个成员变量,年月日都是私有的

class date //声明放在date.h里面
{
public:
private:
	int _year;
	int _month;
	int _day;
};

之前将的四个默认成员函数我们只需要写一个构造函数完成初始化即可,其余三个对内置类型都会完成浅拷贝
构造函数:

date(int year = 1, int month = 1, int day = 1)//全缺省的构造函数
	{
		_year = year;
		_month = month;
		_day = day;
	}

这样就可以设置我们想要的日期了。

对于日期我们可以比较大小,之前在将运算符重载的时候已经讲过了,这里就直接把函数写出来了
日期的比较:

bool date::operator<(const date& d)//定义单独卸载一个文件class.cpp里面
{
	if (_year < d._year)
	{
		return true;
	}
	if (_year == d._year && _month < d._month)
	{
		return true;
	}
	if (_year == d._year && _month == d._month && _day < d._day)
	{
		return true;
	}
	return false;
}

日期的相等:

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

对于日期的大于,大于等于,小于等于,不等于我们可以复用上面两个函数
日期的小于等于:

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);
}

这种复用不只适用于日期类呢,其他类也可以这么使用,这几个都是非常简单,接下来在讲一下另一个运算符

++ --运算符:
对于前置的++ --,我们不需要传参数就行了,返回++ --之后的值

date& date::operator++()//前置加加
{
	return *this += 1;
}


date& date::operator--()//前置减减
{
	return *this -= 1;
}

因为返回的是*this是对象,没有被销毁可以使用引用返回

对于后置++ --,为了和前置区分,多了一个参数,但不做有效参数,相当于一个形式而已:

// 后置++
date date::operator++(int i)//这个i写不写都行,你传过来我也不接收
{
	date tmp(*this);
	*this += 1;
	return tmp;
}
// 后置--
date date::operator--(int)
{
	date tmp(*this);
	*this -= 1;
	return tmp;
}

因为创建了临时对象,所以返回只能使用值返回,虽然会调用拷贝构造,但代价不大,因为前置的和后置的整体差异不大,但前置少了一层拷贝,效率比后置高些,所以尽量能用前置就用前置

接下来我们来介绍一下,有意义的运算符,对于日期加日期没有意义我们就实现,但是日期加减天数有意义,日期减日期也有意义,所以我们来实现一下:

我们在进行一个加天数,是通过这个月有多少天来判断时候需要进到下一个月,所以我们专门写一个函数来获取每个月的天数,在闰年平年的二月我们也做一个判断

int getmonthday(int year,int month)
{
	static int arr[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
	if (month == 2 && ((year % 100 != 0 && year % 4 == 0) || year % 400 == 0))
	{
		return arr[month] + 1;
	}
	else
	{
		return arr[month];
	}
}

这个函数可以写成员函数也可以不用写,我们可以再数组前面加一个static,因为我们要频繁的调用这个函数。

日期加天数:
在这里插入图片描述

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

这么写本身的日期也变成增加之后的日期了,我们需要使用临时变量去进行加减

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

我们发现+=和+这么写不太好
+=用+复用:

date& date::operator+=(int day)
{
	*this=*this+day;
	return *this;
}

+用+=复用:

date date::operator+(int day)
{
	date tmp(*this);
	tmp += day;
	return tmp;
}

大家看这样其中一个代码就简单多了。

日期减天数:
在这里插入图片描述

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 -= day;
	while (tmp._day <= 0)
	{
		tmp._month--;
		if (tmp._month == 0)
		{
			tmp._year--;
			tmp._month = 12;
		}
		tmp._day += getmonthday(tmp._year, tmp._month);
	}
	return tmp;
}

-=用-复用:

date& date::operator-=(int day)
{
	*this=*this-day;
	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 (min > max)
	{
		max = d;
		min = *this;
		flag = -1;
	}
	int count=0;
	while (min != max)
	{
		++min;
		++count;
	}
	return count*flag;
}

我们在来写一个函数将日期打印出来的成员函数:

void print()//当成内联函数
{
	cout << _year << " " << _month << " " << _day << endl;
}

我们来测试一样之前写的所以功能:

在这里插入图片描述
补充程序的细节:
在这里插入图片描述
我们也会遇到这种情况,变成这种情况,我们需要在函数体里面加判断,对于+=,-=也是一样的做法:

if (day < 0)
{
	*this = *this - (-day);
	return *this;
}

if (day < 0)
{
	*this = *this + (-day);
	return *this;
}

这个判断,不要再复用的函数的里面加。这样就和我们网页的日期计算有差不多的功能了。

初始化错误的日期:

date d1(2023,24,35);

这样显然是不可以的,所有初始化都是通过构造函数来完成的,我们再构造函数里面加以个判断就好了

	date(int year = 1, int month = 1, int day = 1)//全缺省的构造函数
	{
		if (day > 0 && day <= getmonthday(year, month) && month > 0 && month < 13)
		{
			_year = year;
			_month = month;
			_day = day;
		}
		else
		{
			cout << "非法初始化" << endl;
			assert(false);
		}
	}

完整的代码:

#include"date.h"
int main()
{
	date d1(2023, 5, 4);
	cout << "测试日期加天数:" << endl;
	d1.print();
	date d2=d1 + (-400);
	d1.print();
	d2.print();
	printf("\n");

	cout << "测试日期减天数:" << endl;
	date d3(2023,5,4);
	d3.print();
	date d4 = d3 - (-400);
	d3.print();
	d4.print();
	printf("\n");

	cout << "测试日期加等天数:" << endl;
	date d5(2022, 3, 30);
	d5.print();
	d5 += -400;
	d5.print();
	printf("\n");

	cout << "测试日期减等天数:" << endl;
	date d6(2022, 3, 30);
	d6.print();
	d6 -= -400;
	d6.print();
	printf("\n");

	cout << "测试后置++:" << endl;
	date d7(2023, 5, 4);
	d7++.print();
	d7.print();
	printf("\n");


	cout << "测试后置减减:" << endl;
	date d8(2023, 5, 4);
	d8--.print();
	d8.print();
	printf("\n");


	cout << "测试前置加加:" << endl;
	date d9(2023, 5, 4);
	(++d9).print();
	d9.print();
	printf("\n");

	cout << "测试测试前置减减:" << endl;
	date d10(2023, 5, 4);
	(--d10).print();
	d10.print();
	printf("\n");

	cout << "测试日期减日期:" << endl;
	date d11(2023, 5, 6);
	date d12(2003, 3, 25);
	int ret = d11 - d12;
	cout << ret << endl;
	return 0;

}

#include<iostream>

using namespace std;
class date 
{
public:
	date(int year = 1, int month = 1, int day = 1)//全缺省的构造函数
	{
		_year = year;
		_month = month;
		_day = day;
	}
	//拷贝构造
	//赋值重载
	//析构函数

	void print()//当成内联函数
	{
		cout << _year << " " << _month << " " << _day << endl;
	}
	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);

	int date::getmonthday(int year,int month);

	// 日期-天数
	date operator-(int day);
	// 日期-=天数
	date& operator-=(int day);

	// 前置++
	date & operator++();
	// 后置++
	date operator++(int);
	// 后置--
	date operator--(int);
	// 前置--
	date& operator--();

	int operator-(const date& d);

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


#include"date.h"
bool date::operator<(const date& d)
{
	if (_year < d._year)
	{
		return true;
	}
	if (_year == d._year && _month < d._month)
	{
		return true;
	}
	if (_year == d._year && _month == d._month && _day < d._day)
	{
		return true;
	}
	return false;
}

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


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 || (*this) == d;
}
bool date::operator!=(const date& d)
{
	return !(*this == d);
}

int date::getmonthday(int year,int month)
{
	static int arr[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
	if (month == 2 && ((year % 100 != 0 && year % 4 == 0) || year % 400 == 0))
	{
		return arr[month] + 1;
	}
	else
	{
		return arr[month];
	}
}
date& date::operator+=(int day)
{
	if (day < 0)
	{
		*this = *this - (-day);
		return *this;
	}
	_day += day;
	while(_day > getmonthday(_year,_month))
	{
		_day -= getmonthday(_year, _month);
		_month += 1;
		if (_month == 13)
		{
			_year += 1;
			_month = 1;
		}
	}
	return *this;
}


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

 //日期-天数
date date::operator-(int day)
{
	date tmp(*this);
	tmp -= day;
	return tmp;
}
// 日期-=天数
date& date::operator-=(int day)
{
	if (day < 0)
	{
		*this = *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++()
{
	return *this += 1;
}
// 后置++
date date::operator++(int)
{
	date tmp(*this);
	*this += 1;
	return tmp;
}
// 后置--
date date::operator--(int)
{
	date tmp(*this);
	*this -= 1;
	return tmp;
}
// 前置--
date& date::operator--()
{
	return *this -= 1;
}
int date::operator-(const date& d)
{
	date max = *this;
	date min = d;
	int flag = 1;
	if (min > max)
	{
		max = d;
		min = *this;
		flag = -1;
	}
	int count=0;
	while (min != max)
	{
		++min;
		++count;
	}
	return count*flag;
}

总结

对于这个类的实现,综合性特别强,将之前我讲到四个默认的成员函数弄懂,理解这个类不是问题,有许多代表性很强的函数,函数的复用等等。所以大家一定要好好理解这个类,对大家的帮助很大,下篇我将通过这个类再来讲解一个运算符重载,大家再来理解里面的知识和注意的细节。
在这里插入图片描述

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

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

相关文章

企业数字化转型的五个常见问题以及回答

数字化、数字化转型其实并不是新的概念&#xff0c;早在十年前就提出来了&#xff0c;但近两年才开始真正走向公众视野。由于概念的泛滥与传统信息化的双重叠加影响&#xff0c;多数企业存在认知上的诸多困扰。 数字化转型为何成为当前热点&#xff1f; 什么是数字化转型&…

云渲染可以渲动画吗?

云渲染可以渲动画吗&#xff1f; 首先我来回答你这个问题&#xff0c;云渲染当然可以渲动画啦&#xff01;像2022年暑期档最火的动画电影《新神榜&#xff1a;杨戬》就是在云渲染的支持下才能准时上线跟大家见面的哦&#xff01; Renderbus瑞云渲染和追光动画也是老朋友了&…

Android Jetpack Compose的附带效应

Android Jetpack Compose的附带效应 Jetpack Compose 是许多开发人员的首选&#xff0c;因为它具有有趣、简单、有效和直接的特性&#xff0c;并且能够轻松地以声明方式构建自定义组件。但是&#xff0c;要充分利用其功能&#xff0c;重要的是要很好地掌握副作用和效果处理程序…

十六、Java数据结构与算法 - 图

文章目录 一、图的基本介绍1.1 为什么要有图1.2 图的举例说明1.3 图的常用概念 二、图的表示方式2.1 邻接矩阵2.2 邻接表 三、图的快速入门案例四、图的遍历4.1 深度优先遍历DFS4.1.1 基本思想4.1.2 算法步骤4.1.3 图示 4.2 广度优先遍历BFS4.2.1 基本思想4.2.2 算法步骤4.2.3 …

Segment Anything模型部分结构和代码解析

0x0. 前言 上个月Meta提出的Segment Anything Model&#xff08;SAM&#xff09;希望在视觉领域通过Prompt基础大模型的套路来解决目标分割的问题。经过实测&#xff0c;在大多数场景中SAM的表现都足够惊艳&#xff0c;并且基于SAM的各种二创工作也爆发了比如 检测一切的Groun…

Prometheus监控报警-web,域名,端口, 钉钉版本

Prometheus监控报警-web&#xff0c;域名&#xff0c;端口&#xff0c; 钉钉版本 采用文章 https://www.yuque.com/youngfit/qok2pe/nypstd#616a2e58https://www.jianshu.com/p/eae67b770c3ehttps://blog.csdn.net/Sebastien23/article/details/113645177https://www.cnblogs…

Unix套接字(UDS,Unix Domain Socket)

【知识简介】 在​​Linux​​系统中&#xff0c;有很多进程间通信方式&#xff0c;套接字&#xff08;Socket&#xff09;就是其中的一种。但传统的套接字的用法都是基于TCP/IP协议栈的&#xff0c;需要指定IP地址。如果不同主机上的两个进程进行通信&#xff0c;当然这样做没…

BEVFusion A Simple and Robust LiDAR-Camera Fusion Framework 论文学习

论文地址&#xff1a;BEVFusion: A Simple and Robust LiDAR-Camera Fusion Framework 论文学习 Github 地址&#xff1a;BEVFusion: A Simple and Robust LiDAR-Camera Fusion Framework 论文学习 1. 解决了什么问题&#xff1f; 将相机和 LiDAR 融合已经成为 3D 检测任务事…

【MySQL】数据库的增删改查二:CURD

目录 ​ 需要知道 &#x1f31f;一、增加数据 &#x1f308;1、语法 &#x1f308;2、单行数据&#xff0c;全列插入 &#x1f308;3、多行数据&#xff0c;全列插入 &#x1f31f;二、查询数据 &#x1f308;1、全列查询 &#x1f308;2、指定列查询 &#…

Nacos集群部署配置Nginx负载均衡

Nacos集群部署配置Nginx负载均衡 1|新建nacos文件夹 mkdir nacos 新建文件夹 cd nacos 进入文件夹2|下载Nacos安装包&#xff08;前提是云服务器&#xff0c;有网。也可以在windows下载好再上传&#xff09; wget https://github.com/alibaba/nacos/releases/download/2…

新品发布 | 12通道CAN FD转USB接口卡全新上市!

新品发布 ON 05.05 TC1018是同星智能开发的一款12路CAN FD总线转USB接口卡&#xff0c;配合我们的TSMaster软件可以监控、分析和仿真CAN FD总线数据。广泛应用于汽车、工业、特种机械和其他行业&#xff0c;用于CAN总线测试与分析、UDS诊断和ECU刷写等方面。 TC1018-产品简介…

weka3.8.6的安装与使用

目录 背景 一、安装 二、使用explorer 1. 介绍 2.打开自带的数据集(Preprocess) 1.打开步骤 2.查看属性和数据编辑 3.classify 4.Cluster 5.Associate 6.Select attributes 7.Visualize 待补充 背景 Weka的全名是怀卡托智能分析环境&#xff08;Waikato Environme…

进程调度/页面置换/磁盘调度算法

进程调度算法 进程调度算法也称 CPU 调度算法&#xff0c;毕竟进程是由 CPU 调度的。 当 CPU 空闲时&#xff0c;操作系统就选择内存中的某个「就绪状态」的进程&#xff0c;并给其分配 CPU。 什么时候会发生 CPU 调度呢&#xff1f;通常有以下情况&#xff1a; 当进程从运…

AIGC:【LLM(二)】——LangChain:由LLMs驱动的应用开发框架

文章目录 一.背景介绍二.LangChain简介2.1 常见应用场景 三.LangChain特点3.1 优点3.2 不足 四.LangChain功能4.1 基础功能4.2 功能模块4.2.1 LLM和Prompts4.2.2 Chain4.2.3 Agent4.2.4 Memory4.2.5 Embedding4.2.6 Models4.2.7 Indexes 五.实战案例5.1 背景需求5.2 数据准备5.…

抖音seo矩阵系统源码是什么?

抖音SEO矩阵系统源码是一款功能强大的营销工具&#xff0c;能够帮助用户进行抖音视频的SEO优化&#xff0c;使其在抖音平台上获得更高的曝光度和流量。该系统结合了SEO的相关算法和技巧&#xff0c;提供了完整的优化方案&#xff0c;可帮助用户提高视频的曝光率、获得更多的点赞…

阻塞队列原理及Java实现

目录 1.阻塞队列 1.举例&#xff1a;包饺子 1.通过多线程来实现 2.通过阻塞队列来实现 2.消息队列 1.解耦 2.削峰填谷 用消息队列来解决 3.异步操作 3.实现一个阻塞队列 使用循环数组 4.实现生产者和消费者模型 完整代码 5.虚假唤醒 1.概念及原因 2.解决方法 1…

关于GD32替换STM32(pin to pin)搭载rt-thread操作系统,需要注意的问题总结

1、SystemInit()函数 该函数位于启动文件中的Reset_Handler中(具体实现在GD32位于system_gd32f4xx.c&#xff0c;STM32位于system_stm32f4xx.c中&#xff0c;几乎所有的文件&#xff0c;你只要把gd换成st就能找到对应的文件)&#xff0c;gd的叫startup_gd32Fxxx.s&#xff0c;…

4.HIVE函数

1.hive函数 1.1 空值替换 两个输入&#xff1a;nvl(col,default_num) : 如果colum不为null&#xff0c;返回col.否则返回default_num 多个输入&#xff1a;coalesce(col1, col2, col3, ....) &#xff1a;从左到右找第一个不为null的值 例如&#xff1a;求所有员工的平均薪…

【操作系统】总结

依旧是小林coding 的内容 存储架构 现代 CPU 都是多核心的&#xff0c;线程可能在不同 CPU 核心来回切换执行&#xff0c;这对 CPU Cache 不是有利的&#xff0c;虽然 L3 Cache 是多核心之间共享的&#xff0c;但是 L1 和 L2 Cache 都是每个核心独有的&#xff0c;如果一个线…

VMWare安装windows7虚拟机提示Operating System not found

前提&#xff1a;下载windows7 Gost并创建虚拟机&#xff0c;启动报错&#xff1a;Operating System not found 解决办法 用微PE工具制作iso系统&#xff0c;对虚拟机进行分区 下载地址&#xff1a;https://www.wepe.com.cn/ 制作方法&#xff0c;双击安装程序&#xff0c;选…