日期类代码实现-C++
一、目标
通过前面对类和对象的介绍我们可以自己通过C++代码初步实现一个简单的日期类。
实现的主要操作有:
1.日期类的构造函数
2.日期类的拷贝构造函数(在头文件中实现)
3.日期类的比较运算符重载
4.日期类的计算运算符重载
5.流插入运算符重载。
二、总体思路
首先,我这里采用的是分文件编程的方式来实现的日期类。
分别为:
1.头文件:Date.h
该文件的主要目的是对上述目标所要实现的所有操作进行函数的声明。同时,还要包含在
源文件Date.cpp 中定义时所需要用到的头文件函数。
2.源文件:Date.cpp
该文件的目的主要是用于对 头文件Date.h 所声明的所有函数进行定义,从而完成各个函数所要实现的操作。
3.源文件:Test.cpp
该文件的目的主要是用于检测 源文件Date.cpp 中定义的函数是否能正常够使用并且达到所要实现的操作。
三、代码实现及具体思路
1.头文件:Date.h
通过上面思路的介绍,我们可以知道,我们的目的是创建一个日期类,然后在日期类中自我声明:日期类的构造函数、日期类的比较运算符重载、日期类的计算运算符重载以及流插入运算符重载。并实现拷贝构造函数。
(注意:通过我们前面对类和对象的介绍可知,因为在实现日期类过程中,我们没有动态申请空间,所以我们只需使用编译器默认生成的析构函数就可以,因此,我们不需要自己再定义一个析构函数)
代码如下:
#pragma once#include <iostream>
#include <assert.h>using namespace std;
class Date
{public:Date(int year = 1, int month = 1, int day = 1);void Print()const{cout << _year << '-' << _month << '-' << _day << endl;}Date(const Date& d){_year = d._year;_month = d._month;_day = d._day;}//日期类的比较运算符的重载bool operator<(const Date& x) const;bool operator==(const Date& x) const;bool operator<=(const Date& x) const;bool operator>(const Date& x) const;bool operator>=(const Date& x) const;bool operator!=(const Date& x) const;//日期类的计算运算符的重载int Get_MonthDay(int year,int month); //获取该月份的天数Date& operator+=(int day);Date operator+(int day)const;Date& operator-=(int day);Date operator-(int day)const;Date& operator++(); //前置++Date operator++(int); //后置++Date& operator--(); //前置--Date operator--(int); //后置--int operator-(const Date& x) const;// 流插入不能写成成员函数?// 因为Date对象默认占用第一个参数,就是做了左操作数// 写出来就一定是下面这样子,不符合使用习惯//d1 << cout; // d1.operator<<(cout); //void operator<<(ostream& out);// 友元函数声明friend ostream& operator<<(ostream& out, const Date& d);friend istream& operator>>(istream& in, Date& d);
private:int _year;int _month;int _day;
};ostream& operator<<(ostream& out, const Date& x);
istream& operator>>(istream& in, Date& x);
2.源文件:Date.cpp
对于实现下面函数,我们需要首先定义一个获取当前月份天数的函数
代码实现:
//因为平年闰年的2月天数不一样所以我们需定义一个获取月份的函数来解决这一问题
int Date::Get_MonthDay(int year, int month) //获取该月份的天数
{static int daysArr[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };if (month == 2 && (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)){return 29;}else{return daysArr[month];}
}
1.日期类的构造函数
思路:
我们在通过日期类构造函数初始化所定义的日期时,我们需要判断我们所定义的日期是否合法,若不合法,则需要返回并提示
代码实现:
Date::Date(int year, int month, int day)
{//判断所初始化的日期是否合法if (month > 0 && month < 13&&day>=1&&day<= Get_MonthDay(year, month)){_year = year;_month = month;_day = day;}else{cout << "非法日期" << endl;assert(false);}
}
2.日期类的比较运算符重载
思路:
对于比较类的运算符重载来说,因为比较运算符具有互斥性,所以我们只需定义出 < 运算符重载和 == 运算符重载,然后其他运算符复用上面所定定义的两个运算符即可。并且在比较的同时,我们不会改变参数的值,所以我们可以在函数尾部加const用于修饰内部的this指针,这样的话,const修饰的类型我们也可以通过比较运算符来比较。
代码实现:
bool Date::operator<(const Date& x) const
{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;}else{return false;}
}bool Date::operator==(const Date& x) const
{if (_year == x._year && _month == x._month && _day == x._day){return true;}else{return false;}
}bool Date::operator<=(const Date& x) const
{//复用上面定义的重载运算符:< , ==return *this < x || *this == x;
}bool Date::operator>(const Date& x) const
{//复用上面定义的重载运算符:<=return !(*this <= x);
}bool Date::operator>=(const Date& x) const
{//复用上面定义的重载运算符:> , ==return *this > x || *this == x;
}bool Date::operator!=(const Date& x) const
{//复用上面定义的重载运算符:==return !(*this == x);
}
3.日期类的计算运算符重载
思路:
对于日期类的计算运算符重载的定义,我们可以先定义 += 运算符重载和 -= 运算符重载,然后其他运算符重载的定义我们可以复用这两个运算符重载,从而实现各个运算符所要实现的目的。
代码实现:
Date& Date::operator+=(int day)
{if (day < 0){return *this -= (-day);}_day = _day + day;while (_day > Get_MonthDay(_year, _month)){_day = _day-Get_MonthDay(_year, _month);++_month;if (_month == 13){_month = 1;++_year;}}return *this;
}Date Date::operator+(int day)const
{if (day < 0){return *this - (-day);}//复用上面定义的重载运算符:+=Date tem(*this);tem+= day;return tem;
}Date& Date::operator-=(int day)
{if (day < 0){return *this += (-day);}_day = _day - day;while (_day < 1){--_month;if (_month <1 ){_month = 12;--_year;}_day = _day + Get_MonthDay(_year, _month);}return *this;
}Date Date::operator-(int day)const
{if (day < 0){return *this + (-day);}//复用上面定义的重载运算符:-=Date tem(*this);tem -= day;return tem;
}Date& Date::operator++()
{//复用上面定义的重载运算符:+=*this += 1;return *this;
}Date Date::operator++(int)
{//复用上面定义的重载运算符:+Date tem = *this;*this += 1;return tem;
}Date& Date::operator--()
{//复用上面定义的重载运算符:+=*this -= 1;return *this;
}Date Date::operator--(int)
{//复用上面定义的重载运算符:+Date tem = *this;*this -= 1;return tem;
}
实现两个日期之间相减求天数时,我们可以先判断哪个日期大,从而确定出所求的天数是正数还是负数,即用flage的正负来实现。接着我们定义一个n来统计天数,然后我们通过while循环,++最小的日期,并且++天数直到最小日期和最大日期相等的时候结束,这时候我们返回n*flage的值即是所求天数。
int Date::operator-(const Date& x) const
{Date max = *this;Date min = x;int flage = 1;if (*this < x){max = x;min = *this;flage = -1;}int n = 0;while (min != max){++min;++n;}return n * flage;
}
4.流插入运算符重载。
思路:
对于日期类使用系统中的流插入(只能插入内置类型)时并不能实现所期望的操作,因为日期类是自定义类型,所以我们就需要自己定义一个流插入来实现这个操作
// 流插入不能写成成员函数?// 因为Date对象默认占用第一个参数,就是做了左操作数// 写出来就一定是下面这样子,不符合使用习惯//d1 << cout; // d1.operator<<(cout); //void operator<<(ostream& out);
因此,这里我们通过友元函数,在全局中定义流插入的运算符重载
代码实现:
ostream& operator<<(ostream& out, const Date& x)
{out << x._year << "年" << x._month << "月" << x._day << "日" << endl;return out;
}istream& operator>>(istream& in, Date& x)
{int year, month, day;in >> year >> month >> day;if (month > 0 && month < 13&& day > 0 && day <= x.Get_MonthDay(year, month)){x._year = year;x._month = month;x._day = day;}else{cout << "非法日期" << endl;assert(false);}return in;
}
3.源文件:Test.cpp
Test1:
用于检测日期类的比较运算符的重载
void Test1() //用于检测日期类的比较运算符的重载
{Date s1(2005, 2, 16);Date s2(2024, 8, 12);cout << "bool operator<(const Date& x) const:" << (s1 < s2) << endl;cout << "bool operator==(const Date& x) const:" << (s1 == s2) << endl;cout << "bool operator<=(const Date& x) const:" << (s1 <= s2) << endl;cout << "bool operator>(const Date& x) const:" << (s1 > s2) << endl;cout << "bool operator>=(const Date& x) const:" << (s1 >= s2) << endl;cout << "bool operator!=(const Date& x) const:" << (s1 != s2) << endl;
}
Test2:
用于检测日期类的计算运算符的重载:+= , +
void Test2() //用于检测日期类的计算运算符的重载:+= , +
{Date s1(2005, 2, 16);s1.Print();s1 += 10000;s1.Print();Date s2(2005, 2, 16);s2.Print();Date s3=s2+10000;s3.Print();
}
Test3:
用于检测日期类的计算运算符的重载:-= , -
void Test3() //用于检测日期类的计算运算符的重载:-= , -
{Date s1(2005, 2, 16);s1.Print();s1 -= 1000;s1.Print();Date s2(2005, 2, 16);s2.Print();Date s3 = s2 - 1000;s3.Print();
}
Test4:
用于检测日期类的计算运算符的重载:--
void Test4() //用于检测日期类的计算运算符的重载:--
{Date s2(2005, 2, 16);Date s3(2005, 2, 16);Date s4;s4=s2--;s4.Print();s4 = --s3;s4.Print();
}
Test5:
用于检测日期类的计算运算符的重载:++
void Test5() //用于检测日期类的计算运算符的重载:++
{Date s2(2005, 2, 16);Date s3(2005, 2, 16);Date s4;s4 = s2++;s4.Print();s4 = ++s3;s4.Print();
}
Test6:
用于检测日期类之间的计算运算符的重载:-
void Test6() //用于检测日期类之间的计算运算符的重载:-
{Date s1(2005, 2, 16);Date s2(2024, 8, 13);cout << "int operator-(const Date& x) const:" << (s1 - s2) << endl;
}
Test7:
用于检测日期类之间的计算运算符的重载:<< , >>
void Test7() //用于检测日期类之间的计算运算符的重载:<< , >>
{Date s1;cin >> s1;cout << s1 << endl;cout << s1 + 100 << endl;
}
四、结语:
上述内容,即是我个人对C++日期类的个人见解及代码实现。若有大佬发现哪里有问题可以私信或评论指教一下。非常感谢各位uu们的点赞,关注,收藏,还望各位多多关照,让我们一起进步吧!
相关文章:

日期类代码实现-C++
一、目标 通过前面对类和对象的介绍我们可以自己通过C代码初步实现一个简单的日期类。 实现的主要操作有: 1.日期类的构造函数 2.日期类的拷贝构造函数(在头文件中实现) 3.日期类的比较运算符重载 4.日期类的计算运算符重载 5.流插入运…...

【问题记录+总结】VS Code Tex Live 2024 Latex Workshop Springer模板----更新ing
目录 Summary 道阻且长 少即是多 兵马未动粮草先行 没有万能 和一劳永逸 具体问题具体分析 心态 Detail 1、关于模板[官网] 2、settings.json 3、虫和杀虫剂 4、擦 换成Tex Studio都好了。。。 Summary 道阻且长 某中意期刊,只有Latex。之前只简单用过…...
Linux运维_Bash脚本_源码安装Go-1.21.11
Linux运维_Bash脚本_源码安装Go-1.21.11 Bash (Bourne Again Shell) 是一个解释器,负责处理 Unix 系统命令行上的命令。它是由 Brian Fox 编写的免费软件,并于 1989 年发布的免费软件,作为 Sh (Bourne Shell) 的替代品。 您可以在 Linux 和…...

ShareSDK Twitter
创建应用 1.登录Twitter控制台并通过认证 2.点击Developer Portal进入Twitter后台 3.点击Sign up for Free Account创建应用 4.配置应用信息 以下为创建过程示例,图中信息仅为示例,创建时请按照真实信息填写,否则无法正常使用。 权限申请…...
word2vec 如何用多个词表示一个句子
word2vec 模型通常用于将单词映射为固定大小的向量。为了使用多个词表示一个句子,我们可以采用以下几种方法: 词袋模型 (Bag of Words, BoW): 将句子中所有词的向量加起来,不考虑词的顺序。这种方法简单,但会丢失词序信息。 计算…...

IDEA中查看接口的所有实现类和具体实现类
1.IDEA中接口的所有实现类查看 1.CTRLH(hierarchy 结构) 我们选中要查看的接口 按住快捷键ctrlh 在界面右侧可以看到该接口的所有可能实现类 2.右击diagrams->show diagram 选中要查看的接口 右击选择diagrams->show diagram 即可以以图表的方式查看接口和所有实现类…...

DLL的导出和调用
动态链接库在C中非常重要,写了一个简单的例子用于DLL的导出和调用。 DLL的生成 头文件 #include<iostream> #include<stdexcept> using namespace std;#define TESTAPI __declspec(dllexport)// 函数定义 extern "C" {TESTAPI int add(in…...
vscode中调试cuda kernel
关于vscode中调试cpp可参考之前的博客:ubuntu vscode 基本设置 和 调试设置_ubuntu vscode 调试-CSDN博客 这篇我们来讲如何调试.cu的kernel,主要参考的是:https://www.zhihu.com/question/431782036/answer/2468791220 1、基本准备不多说&am…...
SQL的连接查询与pandas的对应关系
在SQL和Pandas中,连接查询(join)是处理数据集之间关系的重要工具。下面是SQL中的各种连接查询类型及其与Pandas中相应操作的对应关系: 1. INNER JOIN SQL: INNER JOIN 返回两个表中具有匹配值的行。 Pandas: merge() 方法的 how…...
【JS】中断和恢复任务序列
前言 封装processTasks函数,实现以下需求 /*** 依次顺序执行一系列任务* 所有任务全部完成后可以得到每个任务的执行结果* 需要返回两个方法,start用于启动任务,pause用于暂停任务* 每个任务具有原子性,即不可中断,只…...

CentOS系统下安装NVIDIA显卡驱动
一、安装显卡驱动 1.安装依赖项 yum -y install gcc pciutils yum -y install gcc yum -y install gcc-c yum -y install make2.查看内核版本 uname -a3.查看显卡版本 lspci | grep -i nvidia4.屏蔽系统自带的nouveau (1)查看nouveau lsmod | grep nouveau (2)打开blackl…...

Linux 与 Windows 服务器操作系统 | 全面对比
在服务器操作系统的领域,Linux 和 Windows 一直是两个备受关注的选择。 首先来看 Windows 操作系统。它由 Microsoft Corporation 开发,在桌面领域占据显著份额,其中 Windows 10 是使用最广泛的版本,广泛应用于个人计算机和企业桌…...
给既有exe程序添加一机一码验证
原文地址:李浩的博客 lihaohello.top 本科期间开发过一款混凝土基本构件设计程序,该程序是一个独立的exe可执行文件,采用VC静态链接MFC库编制而成。近期,需要为该程序添加用户注册验证的功能,从而避免任何用户获取该程…...

【Datawhale X 魔搭 】AI夏令营第四期大模型方向,Task2:头脑风暴会,巧灵脑筋急转弯(持续更新)
队伍名称:巧灵脑筋急转弯 队伍技术栈:python,LLM,RAG,大模型,nlp,Gradio,Vue,java 队友:知唐(队长),我真的敲不动…...
mysql 多个外键
在MySQL中,一个表可以有多个外键约束,它们分别关联到不同的主表。在创建表时,可以在每个外键约束上指定不同的外键名称。以下是一个简单的例子,演示如何在创建表时定义多个外键: CREATE TABLE orders (order_id INT AU…...

解决方案上新了丨趋动科技推出基于银河麒麟操作系统的异构算力池化解决方案
趋动科技携手麒麟软件打造基于银河麒麟操作系统的异构算力池化解决方案,共同探索AI领域新场景。 人工智能技术作为数字经济发展的重要推手,在各行业业务场景中落地需要大量AI算力资源的有效保障。在IT基础设施普遍云化的今天,AI算力一方面需…...
14.创建一个实战maven的springboot项目
项目核心主要部分 pom.xml文件 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://mave…...

docker部署LNMP
docker部署LNMP nginx 1.22 172.111.0.10 docker-nginx mysql 8.0.30 172.111.0.20 docker-mysql php 8.1.27 172.111.0.30 docker-php docker:单节点部署,只能在一台机器上部署,如果跨机器容器无法操作,无法通信。 做高可用…...
在Spring Boot应用中,如果你希望在访问应用时加上项目的名称或者一个特定的路径前缀
在Spring Boot应用中,如果你希望在访问应用时加上项目的名称或者一个特定的路径前缀 在Spring Boot应用中,如果你希望在访问应用时加上项目的名称或者一个特定的路径前缀,你可以通过配置server.servlet.context-path属性来实现。这通常在app…...
东南大学:Wi-Fi 6搭档全光以太,打造“数智东南”信息高速路
东南大学:Wi-Fi 6搭档全光以太,打造“数智东南”信息高速路 - 华为企业业务 打好ICT底座,平台和应用层面就会非常通畅了。首先,出海企业的需求既有普遍性,也有垂直性行业的特性需求。普遍性需求需要通信、沟通数据和传…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...

7.4.分块查找
一.分块查找的算法思想: 1.实例: 以上述图片的顺序表为例, 该顺序表的数据元素从整体来看是乱序的,但如果把这些数据元素分成一块一块的小区间, 第一个区间[0,1]索引上的数据元素都是小于等于10的, 第二…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...

python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...
React Native在HarmonyOS 5.0阅读类应用开发中的实践
一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强,React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 (1)使用React Native…...
工程地质软件市场:发展现状、趋势与策略建议
一、引言 在工程建设领域,准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具,正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...
Nginx server_name 配置说明
Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...

04-初识css
一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...