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…...
突破GitHub访问瓶颈:Fast-GitHub工具如何实现极速访问体验
突破GitHub访问瓶颈:Fast-GitHub工具如何实现极速访问体验 【免费下载链接】Fast-GitHub 国内Github下载很慢,用上了这个插件后,下载速度嗖嗖嗖的~! 项目地址: https://gitcode.com/gh_mirrors/fa/Fast-GitHub 你是否经常遇…...
别再只把Obsidian当笔记软件了!用DeepSeek R1和Copilot插件,打造你的AI驱动第二大脑
从静态笔记到智能伙伴:用DeepSeek R1重构Obsidian的认知边界 当大多数人还在用Obsidian记录会议纪要或整理读书笔记时,一群先锋用户已经将它改造成了会主动思考的"数字大脑"。想象一下:清晨打开笔记软件,AI助手不仅整理…...
Nintendo Switch游戏文件管理终极指南:告别繁琐操作,NSC_BUILDER让一切变得简单
Nintendo Switch游戏文件管理终极指南:告别繁琐操作,NSC_BUILDER让一切变得简单 【免费下载链接】NSC_BUILDER Nintendo Switch Cleaner and Builder. A batchfile, python and html script based in hacbuild and Nuts python libraries. Designed init…...
5步让2008-2017款旧Mac免费升级最新macOS系统:OpenCore Legacy Patcher完整指南
5步让2008-2017款旧Mac免费升级最新macOS系统:OpenCore Legacy Patcher完整指南 【免费下载链接】OpenCore-Legacy-Patcher Experience macOS just like before 项目地址: https://gitcode.com/GitHub_Trending/op/OpenCore-Legacy-Patcher 你是否还在使用20…...
Qwen2.5-VL-7B-Instruct部署教程:GPU算力监控(nvidia-smi)+服务健康检查脚本
Qwen2.5-VL-7B-Instruct部署教程:GPU算力监控(nvidia-smi)服务健康检查脚本 1. 项目概述 Qwen2.5-VL-7B-Instruct是一款强大的多模态视觉-语言模型,能够同时处理图像和文本输入,生成高质量的响应。该模型特别适合需要…...
2026年智能窗帘电机核心揭秘:一颗二极管的原厂选择如何决定体验?
当清晨的第一缕阳光透过窗户,你设定的智能窗帘电机开始平稳、安静地工作,这背后不仅是算法的精准,更是无数微小电子元件的可靠协作。在智能家居设备的核心——电机驱动板上,一颗看似不起眼的二极管,却常常是决定产品成…...
26年前端面试新时代,问了几个AI题没人会怎么给offer???
当“你会不会用Copilot”成了第一题,全场沉默的那三秒,我看到了普通前端的末日。上周,朋友圈被一位36岁老哥的帖子刷屏了。他说自己已经摸清了“前端AI”面试的拷打套路,从被问到卡壳,到能跟面试官聊AI工程化的落地细节…...
如何用Remax快速构建跨平台小程序:React开发者的终极指南
如何用Remax快速构建跨平台小程序:React开发者的终极指南 【免费下载链接】remax 使用真正的 React 构建跨平台小程序 项目地址: https://gitcode.com/gh_mirrors/re/remax Remax是一个让开发者能够使用真正的React构建跨平台小程序的强大框架。通过Remax&am…...
Twine高级技巧:10个提升故事质量的实用方法
Twine高级技巧:10个提升故事质量的实用方法 【免费下载链接】twinejs Twine, a tool for telling interactive, nonlinear stories 项目地址: https://gitcode.com/gh_mirrors/tw/twinejs Twine是一款强大的互动叙事创作工具,让你轻松构建非线性故…...
WPF中DataTrigger动态控制UI元素可见性的实战技巧
1. 为什么需要动态控制UI元素可见性 在WPF应用开发中,经常会遇到需要根据某些条件动态显示或隐藏界面元素的情况。比如当用户勾选某个复选框时显示额外的输入框,或者根据后台数据状态改变界面布局。这种动态交互能够显著提升用户体验,让界面更…...

