C++实现日期类Date(超详细)
个人主页:平行线也会相交💪
欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 平行线也会相交 原创
收录于专栏【C++之路】💌
本专栏旨在记录C++的学习路线,望对大家有所帮助🙇
希望我们一起努力、成长,共同进步。🍓
目录
- 日期类(Date.cpp)成员函数的实现
- 构造函数
- bool类型的运算符重载
- 得到该月有几天GetMonthDay
- 运算符重载+=和+
- 运算符重载-=和-
- 运算符重载前置++和后置++
- 运算符重载前置--后置--
- 两个日期相差几天
- 日期类(Date.h)
- 日期测试
- TestDate1()
- TestDate2()
- TestDate3()
- TestDate4()
- TestDate5()
- TestDate6()
日期类(Date.cpp)成员函数的实现
//构造函数,声明和定义分析不能同时给缺省参数,一般是声明给缺省参数
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;}
}bool Date::operator<(const Date& x)
{if (_year < x._year){return true;}else if (_year == x._year && _month < x._month){return true;}else if (_year == x._year && _month == x._month && _day < x._day){return true;}return false;
}bool Date::operator==(const Date& x)
{return _year == x._year&& _month == x._month&& _day == x._day;
}bool Date::operator<=(const Date& x)
{return *this < x || *this == x;
}bool Date::operator>(const Date& x)
{return !(*this <= x);
}bool Date::operator>=(const Date& x)
{return !(*this < x);
}bool Date::operator!=(const Date& x)
{return !(*this == x);
}int Date::GetMonthDay(int year, int month)
{//由于要频繁调用daysArr,所以我们把daysArr放到静态区static int daysArr[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };//if ((year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0) && month == 2)if (month == 2 && ((year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0))){return 29;}else{return daysArr[month];}return daysArr[month];
}//+=复用+
//Date& Date::operator+=(int day)
//{
// *this = *this + day;
// return *this;
//}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)
{Date tmp(*this);tmp += day;/*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;*///出了作用域后tmp销毁,所以不能用引用返回return tmp;
}Date& Date::operator -=(int day)
{if (day < 0){return *this += -day;}_day -= day;while (_day <= 0){--_month;if (_month == 0){_month = 13;--_year;}_day += GetMonthDay(_year, _month);}return *this;
}Date Date:: operator-(int day)
{Date tmp = *this;//这里是拷贝构造tmp -= day;return tmp;
}//前置++
Date& Date::operator++()
{*this += 1;return *this;
}//后置++
//增加int参数并不是为了接收具体的值,这里仅仅是占位,为了就是跟前置++构成重载
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;
}//两个日期相差几天
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 (min != max){++min;++n;}return n * flag;
}
构造函数
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;}
}
bool类型的运算符重载
bool Date::operator<(const Date& x)
{if (_year < x._year){return true;}else if (_year == x._year && _month < x._month){return true;}else if (_year == x._year && _month == x._month && _day < x._day){return true;}return false;
}bool Date::operator==(const Date& x)
{return _year == x._year&& _month == x._month&& _day == x._day;
}bool Date::operator<=(const Date& x)
{return *this < x || *this == x;
}bool Date::operator>(const Date& x)
{return !(*this <= x);
}bool Date::operator>=(const Date& x)
{return !(*this < x);
}bool Date::operator!=(const Date& x)
{return !(*this == x);
}
得到该月有几天GetMonthDay
int Date::GetMonthDay(int year, int month)
{//由于要频繁调用daysArr,所以我们把daysArr放到静态区static int daysArr[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };//if ((year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0) && month == 2)if (month == 2 && ((year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0))){return 29;}else{return daysArr[month];}return daysArr[month];
}
运算符重载+=和+
这里有两种方式来写+=和+的赋值运算符重载。
先来看第一种:+=复用+的方式,请看:
Date& Date::operator+=(int 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)
{Date tmp(*this);tmp += day;/*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;*///出了作用域后tmp销毁,所以不能用引用返回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;}}//出了作用域后tmp销毁,所以不能用引用返回return tmp;
}//+=复用+
Date& Date::operator+=(int day)
{*this = *this + day;return *this;
}
现在这两种写法哪一种好呢?对于每种方式的+的赋值运算符重载没啥太大的区别(都要都要创建两个对象,一个是Date tmp(*this);,另外一个就是return tmp);但是对于+=的赋值运算符重载,第一种方式并没有创建对象,而第二种方式的+=的符重运算符重载由于又调用了一次+的赋值运算符重载函数(即多创建了两个对象)。所以最终第一种方式(+复用+=)显然更好一些,第二种方式差就差再+=复用+的时候多创建了两个对象。
运算符重载-=和-
Date& Date::operator -=(int day)
{if (day < 0){return *this += -day;}_day -= day;while (_day <= 0){--_month;if (_month == 0){_month = 13;--_year;}_day += GetMonthDay(_year, _month);}return *this;
}Date Date:: operator-(int day)
{Date tmp = *this;//这里是拷贝构造tmp -= day;return tmp;
}
运算符重载前置++和后置++
//前置++
Date& Date::operator++()
{*this += 1;return *this;
}//后置++
//增加int参数并不是为了接收具体的值,这里仅仅是占位,为了就是跟前置++构成重载,方便区分
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;
}
两个日期相差几天
//两个日期相差几天
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 (min != max){++min;++n;}return n * flag;
}
日期类(Date.h)
class Date
{
public://构造函数Date(int year = 22, int month = 5, int day = 20);//不需要写拷贝构造函数,所以下面可以选择直接注释掉Date (const Date& d){cout << "Date(const Date& d)" << endl;_year = d._year;_month = d._month;_day = d._day;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}bool operator<(const Date& x);bool operator==(const Date& x);bool operator<=(const Date& x);bool operator>(const Date& x);bool operator>=(const Date& x);bool operator!=(const Date& x);int GetMonthDay(int year, int month);Date& operator+=(int day);Date operator+(int day);Date& operator -=(int day);Date operator-(int day);Date& operator++();//前置++Date operator++(int);//后置++Date& operator--();//前置--Date operator--(int);//后置++//计算两个日期相差多少天int operator-(const Date& d);
private:int _year;int _month;int _day;
};
日期测试
TestDate1()

void TestDate1()
{Date da1(23, 5, 20);da1 += 100;da1.Print();Date da2(23, 5, 20);Date da3(da2 + 100);da2.Print();da3.Print();//用一个已经存在的对象初始化另一个对象,即拷贝构造函数//拷贝构造的意义就是赋值初始化Date da4 = da2;//等价于Date da4(da2);//均为拷贝构造函数,是等价的//而赋值重载的意义纯粹的就是拷贝//已经存在的两个对象之间进行复制拷贝,即运算符重载函数da4 = da1;
}
这里指的注意的是Date da4 = da2;是等价于Date da4(da2);,因为这里实在用一个已经存在的对象初始化另外一个对象,所以这里调用的是拷贝构造函数,而不是调用=的赋值运算符重载。
如下如:


TestDate2()
{Date da1(2021, 5, 21);//无论前置还是后置++都需要++//前置++就返回++以后的对象,后置++就返回++之前的对象//编译器这里成全一个同时委屈一个,为了区分这里的重载++da1;//da1.operator++()da1++;//da1.operator++(0)Date da2(2024, 5, 20);Date da3(2023, 3, 14);bool ret1 = da2 < da3;//自定义类型转换为对应的函数int i = 0, j = 2;bool ret2 = i < j;//内置类型编译器知道怎么比较,故编译器会自动处理内置类型的重载
}
TestDate3()
//测试日期类的-=
void TestDate3()
{Date da1(2023, 5, 20);da1 -= 50;da1.Print();Date da2(2023, 5, 21);da2 -= 88;da2.Print();Date da3(2023, 5, 25);da3 -= 100;da3.Print();Date da4(2024, 5, 20);da4 -= 10000;da4.Print();
}
TestDate4()
void TestDate4()
{Date d1(2020, 5, 20);d1 += 100;d1.Print();Date da2(2023, 5, 21);da2 += -100;da2.Print();Date da3(2023, 5, 5);da3 -= -100;da3.Print();
}
TestDate5()
void TestDate5()
{Date da1(2023, 5, 5);Date ret1 = da1--;//调用da1.operator(&da1,0);ret1.Print();da1.Print();Date da2(2023, 5, 5);Date ret2 = --da2;//调用da1.operator++(&da1);ret2.Print();da2.Print();
}
TestDate6()
void TestDate6()
{Date da1(2023, 5, 20);Date da2(2022, 5, 21);Date da3(1949, 10, 1);Date da4(2023, 5, 20);cout << da1 - da2 << endl;cout << da2 - da1 << endl;cout << da3 - da4 << endl;cout << da4 - da3 << endl;
}
好了,以上就是用C++来实现日期类。
就到这里,再见啦各位!!!

相关文章:
C++实现日期类Date(超详细)
个人主页:平行线也会相交💪 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 平行线也会相交 原创 收录于专栏【C之路】💌 本专栏旨在记录C的学习路线,望对大家有所帮助🙇 希望我们一起努力、成长&…...
实验室检验系统源码,集检验业务、质量控制、报告、统计分析、两癌等模块于一体
云 LIS 系统针对区域化 LIS 而设计,依托底层云架构,将传统的 LIS 功能模块进行“云化”。 该系统是集检验业务、科室管理、质量控制、报告、统计分析、两癌等模块于一体的数据检验信息平台。通过计算机联网,实现各类仪器数据结果的实时自动接…...
学习RHCSA的day.03
目录 2.6 Linux系统的目录结构 2.7 目录操作命令 2.8 文件操作命令 2.6 Linux系统的目录结构 1、Linux目录结构的特点 分区加载于目录结构: 使用树形目录结构来组织和管理文件。整个系统只有一个位于根分区的一个根目录(树根)、一棵树。…...
电子邮件协议(SMTP,MIME,POP3,IMAP)
SMTP 关键词: 电子邮件协议:SMTP简单邮件传输协议,负责将邮件上传到服务器,采用TCP的25端口,C/S工作。仅传送ASCII码文本 详细介绍: SMTP是一种提供可靠且有效的电子邮件传输的协议。SMTP是建立在FTP文件传输服务上…...
Golang笔记:使用embed包将静态资源嵌入到程序中
文章目录 目的使用演示//go:embed 指令在WebServer中应用总结 目的 Golang编译程序默认是静态编译,会把相关的库都打包到一起,这在分发部署使用时非常方便。不过如果项目中用到的外部的静态资源文件,通常就需要将这些资源和程序一起拷贝分发…...
ImportError: cannot import name ‘OldCsv‘ from ‘pyflink.table.descriptors‘
我最近开始使用flink用于数据处理。 当我尝试执行table api 用于计数时 我不能导入OldCsv and FileSystem from pyflink.table.descriptors. I have also downloaded apache-flink using: pip install apache-flink [rootmaster flink]# pip3 list | grep flink apache-fli…...
YouCompleteMe(YCM)安装
vim在各个linux版本中是个比较好编辑器,反正nano我是用不惯。但这个ycm的安装也是不断的在变,现在的安装比之前要简单的多,基本个几命令就搞定了,而且 也不用关心系统里有没有vim,ycm已经可以自动安装。具体安装步骤如下ÿ…...
day33_css
今日内容 零、 复习昨日 一、CSS 零、 复习昨日 见代码 一 、引言 1.1CSS概念 层叠样式表(英文全称:Cascading Style Sheets)是一种用来表现HTML(标准通用标记语言的一个应用)或XML(标准通用标记语言的一个子集)等文…...
10个最流行的向量数据库【AI】
矢量数据库是一种将数据存储为高维向量的数据库,高维向量是特征或属性的数学表示。 每个向量都有一定数量的维度,范围从几十到几千不等,具体取决于数据的复杂性和粒度。 推荐:用 NSDT场景设计器 快速搭建3D场景。 矢量数据库&…...
vite3+vue3 项目打包优化二 —— 依赖分包策略
在没有配置构建工具的分包功能时,构建出来的文件将无比巨大且是独立的一个 js 和 css 文件(如下图),这样本地加载文件时会存在巨大的压力。 默认情况下,浏览器重复请求相同名称的静态资源时,会直接使用缓存…...
中国社科院与美国杜兰大学金融管理硕士——与时间赛跑,充分利用每一分钟
不管你愿不愿意,时间总是在不经意间流去。林清玄在《和时间赛跑》中写道:“虽然我知道人永远跑不过时间,但是可以比原来快跑几步。那几步虽然很小很小,但作用却很大很大”。是的,我们需要与时间赛跑,充分利…...
什么是Dirichlet分布?
Dirichlet分布是一种概率分布,用于描述多维随机变量的概率分布。它是一个连续分布,通常用于处理具有多种可能取值的离散型随机变量。在LDA模型中,Dirichlet分布通常被用作先验分布,用来表示主题的概率分布和单词的概率分布。 Dir…...
web前端开发需要哪些技术?学前端顺序千万千万不要搞错啦!
宝子们,下午好,之前给大家分享了前端岗位的前景规划,小源看的出来,还是有不少宝子想入行前端的! 那除了会面试,还要有充足丰富的知识储备,需要什么技术,怎么样做才能找到高薪工作呢&…...
【AFNetWorking源码(二)AFURLSessionManger和AFHTTPSessionManager】
前言 学习了Mananger的初始化和以GET请求为例的过程,发现整个过程离不开AFHTTPSessionManager和AFURLSessionManger的某些方法。这两个是AFN的重要的网络通信模块内容,对它们作揖详细的学习。 AFURLSessionManager和AFHTTPSessionManager都是AFNetwork…...
编程不头秃,Google「AI程序员」来了,聊天就能敲代码
上周 Google 在 I/O 大会宣布了一个能够辅助编程的聊天机器人 Codey,现在它终于上线 Google Colab 啦! 🌟 Codey 是基于 Google 目前最新的大语言模型 PaLM 2 运行,有着强大的语言理解和编程能力。 Codey 有这些功能࿱…...
【数据结构与算法】基础数据结构
文章目录 数组概述动态数组二维数组局部性原理越界检查 链表概述单向链表单向链表(带哨兵)双向链表(带哨兵)环形链表(带哨兵) 队列概述链表实现环形数组实现 栈概述链表实现数组实现应用 双端队列概述链表实…...
k8s系列(四)——资源对象
k8s系列四——资源对象 pod概念 思考:为什么k8s会引出pod这个概念,容器不能解决么? 我的理解:一组密切相关的服务使用容器的话,如果他们的镜像不在一个容器里的话,那么就需要配置反向代理进行通信…...
JavaScript如何使用for循环
JavaScript 是一门非常有趣的编程语言,它可以让我们在浏览器中创建交互式的 Web 应用程序。在 JavaScript 中,我们可以使用 for 循环来迭代一个数组或对象,从而执行一系列的操作。下面是一些关于 for 循环的有趣的用法和例子。 为什么要使用…...
(浙大陈越版)数据结构 第三章 树(上) 3.1 树和树的表示
目录 3.1.1 引子(顺序查找) 什么是树 查找 3.1.2 引子 二分查找例子(BinarySearch) 二分查找 3.1.3 引子 二分查找实现 二分查找代码 二分查找的启示 3.1.4 树的定义 一些基本术语: 3.1.5 树的表示 3.1.1 引子(顺序查找…...
平抑风电波动的电-氢混合储能容量优化配置(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...
调用支付宝接口响应40004 SYSTEM_ERROR问题排查
在对接支付宝API的时候,遇到了一些问题,记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...
UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...
蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练
前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1):从基础到实战的深度解析-CSDN博客,但实际面试中,企业更关注候选人对复杂场景的应对能力(如多设备并发扫描、低功耗与高发现率的平衡)和前沿技术的…...
2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...
拉力测试cuda pytorch 把 4070显卡拉满
import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试,通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小,增大可提高计算复杂度duration: 测试持续时间(秒&…...
AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别
【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而,传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案,能够实现大范围覆盖并远程采集数据。尽管具备这些优势…...
scikit-learn机器学习
# 同时添加如下代码, 这样每次环境(kernel)启动的时候只要运行下方代码即可: # Also add the following code, # so that every time the environment (kernel) starts, # just run the following code: import sys sys.path.append(/home/aistudio/external-libraries)机…...
淘宝扭蛋机小程序系统开发:打造互动性强的购物平台
淘宝扭蛋机小程序系统的开发,旨在打造一个互动性强的购物平台,让用户在购物的同时,能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机,实现旋转、抽拉等动作,增…...

