CPP入门:日期类的构建

目录

1.日期类的成员

2.日期类的成员函数

2.1构造和析构函数

2.2检查日期合法

 2.3日期的打印

 2.4操作符重载

2.4.1小于号

2.4.2等于号

2.4.3小于等于号

 2.4.4大于号

2.4.5大于等于号

2.4.6不等号

 2.4.7加等的实现

2.4.8加的实现

2.4.9减去一个天数的减等实现

2.4.10减去一个天数的减实现

2.4.11两个日期相减的实现

 2.4.12前后置++的实现

2.4.13前后置--的实现

 2.5流插入/流提取操作符


1.日期类的成员

实现一个日期类,内部的成员自然是年、月、日

class Date
{private:int _year;int _month;int _day;
};

在日期类中,我们应当是已知每个月份有多少天的,因此我们还需要在日期内中写一个成员函数来获得当月的天数。

	//获得天数int GetMonthDay(int year,int month){static int monthDayArray[13] = { -1, 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 monthDayArray[month];}}

此外,我们的日期类还应当能够实现对日期的打印、对日期类的相关计算、输入输出的重载等成员函数。

因此,我们完整的日期类应是如下:

#pragma once
#include <iostream>
using namespace std;
#include <assert.h>
class Date
{
public://流插入or输出friend ostream& operator<<(ostream& out, const Date& d);friend istream& operator>>(istream& in, Date& d);//构造Date(int year = 1900, int month = 1, int day = 1);//获取月份天数int GetMonthDay(int year, int month){assert(month > 0 && month < 13);static int monthDayArray[13] = { -1, 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 monthDayArray[month];}}//检查日期bool CheckDate();//打印日期void Print() const;//日期类相关计算bool operator<(const Date& d) const;bool operator<=(const Date& d) const;bool operator>(const Date& d) const;bool operator>=(const Date& d) const;bool operator==(const Date& d) const;bool operator!=(const Date& d) const;Date& operator+=(int day);Date operator+(int day) const;Date& operator-=(int day);Date operator-(int day) const;int operator-(const Date& d) const;Date& operator++();Date operator++(int);Date& operator--();Date operator--(int);
private:int _year;int _month;int _day;
};
//输入流重载
ostream& operator<<(ostream& out, const Date& d);
//输出流重载
istream& operator>>(istream& in, Date& d);

2.日期类的成员函数

2.1构造和析构函数

由于日期类的成员都是内置类型,因此我们可以显式的写一个构造函数,但不用显式定义析构函数。

Date::Date(int year = 2024, int month = 7, int day = 2)
{_year = year;_month = month;_day = day;//检查日期合法性if (!CheckDate()){cout << "日期非法" << endl;}
}

由于我们的日期具有范围,因此我们需要在构造函数中检查日期是否合法。也正是因此,我们需要实现一个检查日期合法性的函数。

2.2检查日期合法

检查日期合法,首先要确保我们输入的数是正数,

//检查日期合法性
bool Date::CheckDate()
{if (_month < 1 || _month>12|| _day<1 || _day>GetMonthDay(_year, _month)||_year < 1){return false;}else{return true;}
}

 2.3日期的打印

void Date::Print() const 
{cout << _year <<'-' << _month <<'-'<<_day;
}

 2.4操作符重载

下面我们就需要重载一些对日期类计算有用的操作符

2.4.1小于号

由于我们不想要我们传入的参数会被修改,因此我们需要传递常量。(权限可以缩小)

另外,我们传引用有两个原因

  • 可以少一次构造形参的过程,可以提高性能。
  • d在函数运行结束后不会销毁,不会返回一个空引用。

因此我们的函数名为:

bool operator<(const Date& d) const

 判断一个日期是否小于另一个日期,我们需要分别判断年、月、日是否小于另一个日期。

在判断日的时候,我们可以直接使用原生的<操作符判断。

bool Date::operator<(const Date& d) const
{//年if (_year < d._year){return true;}else if (_year == d._year){   //月if (_month < d._month){return true;}else if (_month == d._month){//日return _day < d._day;//if (_day < d._day)//{//	return true;//}//else//{//	return false;//}}}
}

2.4.2等于号

直接判断年月日是否相等即可 

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

2.4.3小于等于号

我们传入的第一个参数是this,因此我们解引用this即可得到第一个参数的值。 

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

 2.4.4大于号

判断是否大于就是是否小于等于取反 

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

2.4.5大于等于号

 判断是否大于等于就是对判断是否小于取反

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

2.4.6不等号

判断是否不相等就是对判等取反

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

 2.4.7加等的实现

对于加等,是给定一个日期和一个天数,计算日期加上这个天数之后的日期。

这里我们采取的思路是先将原天数加上需要加的天数。

之后我们一直减去当月的天数,并让月份加1,如果月份为13,则年份加1,月份赋为1。一直到天数没有当月天数大为止。

Date& Date::operator+=(int day)
{//日期加_day+= day;//月份加while (_day > GetMonthDay(_year, _month)){if (_day > GetMonthDay(_year, _month)){_month++;_day - GetMonthDay(_year, _month);if (_month == 13){_month == 1;_year += 1;}}}return *this;
}

2.4.8加的实现

首先,我们实现两数相加,是不能改变我们的原数的。

因此,我们的第一个形参为const修饰的变量。

//加
//c=a+b;
Date Date::operator+(int day) const
{Date tmp = *this;tmp += day;return tmp;
}

这里我们采取的思路是创建一个临时变量来保存*this,然后返回tmp加等day的结果即可。

这里需要注意的是,由于这个函数运行结束之后,tmp会先被销毁掉,再进行返回,因此我们如果返回值为引用的话,则会出错。

2.4.9减去一个天数的减等实现

//减去一个天数
//减等
Date& Date::operator-=(int day)
{//减去一个负数if (day < 0){return *this += (-day);}//减去一个整数_day -= day;while (_day < 0){--month;if (_month == 0){_month = 12;_year--;}_day += GetMonthDay(_year, _month);}
}

与实现加等类似的是,这里我们也是类似的步骤,通过一个循环来不断的更新年月日。 

2.4.10减去一个天数的减实现

//减去一个天数
Date Date::operator-(int day)const
{Date tmp = *this;tmp -= day;return tmp;
}

这里和上面的加等相似。 

2.4.11两个日期相减的实现

首先,我们要判断出哪个日期大

之后,我们让小的日期不断加1,直到他们相同。

加了多少次1,两个日期就相隔多少天。 

//两个日期相减
Date Date::operator-(const Date& d)const
{//假设法判断谁大Date max = *this;Date min = d;if (min > max){max = d;min = *this;}//小的日期不断加一天,直到二者相等//设置一个计数器,计数器的值就是两个日期的差值int n = 0;while (min!+ max){min++;n++;}return n;
}

 2.4.12前后置++的实现

由于我们重载++操作符时都是这么写的:

Date::operator++()//前
Date::operator++(int)//后

这样便无法判断到底是调用前置++还是后置++了。

因此,我们规定调用后置++时,形参写一个int。

Date::operator++()//前
Date::operator++(int)//后

前置++非常容易实现,这里不再赘述。 

//前后置++--
Date& Date::operator++()//前
{*this += 1;return *this;
}
Date  Date::operator++(int)//后
{Date tmp = *this;*this + 1;return tmp;
}

后置++是先使用后++的。因此我们创建一个临时变量来保存*this,并在返回tmp前对*this+1。

2.4.13前后置--的实现

Date& Date::operator--()//前
{*this -= 1;return *this;
}
Date Date::operator--(int)//后
{Date tmp = *this;*this - 1;return tmp;
}

 2.5流插入/流提取操作符

 观察下面两行代码,我们发现这两个操作符的第二个操作数才是this。

但是成员函数默认第一个操作数为this,这就产生了问题。

因此我们不能够将这两个函数声明为成员函数。

cout << n << endl;
cin << n ;

我们需要将这两个函数声明在类外,之后通过友元在类内访问即可。

//类内
friend ostream& operator<<(ostream& out, const Date& d);
friend istream& operator>>(istream& in, Date& d);
//定义
ostream& operator <<(ostream& out, const Date& d)
{cout << d._year << '-' << d._month << '-' << d._day;return out;
}
istream& operator>>(istream& in, Date& d)
{in >> d._year >> d._month >> d._day;if (!d.CheckDate()){cout << "日期非法" << endl;}return in;
}

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

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

相关文章

使用瀚高数据库开发管理工具进行数据的备份与恢复---国产瀚高数据库工作笔记008

使用瀚高数据库,备份 恢复数据 然后找到对应的目录 其实就是hgdbdeveloper,瀚高的数据库开发管理工具 对应的包中有个dbclient 这个目录,选中这个目录以后,就可以了,然后 在对应的数据库,比如 data_middle 中,选中 某个模式,比如bigdata_huiju 然后右键进行,点击 恢复,然…

Verilog开源项目——百兆以太网交换机(五)TCAM单元设计

Verilog开源项目——百兆以太网交换机&#xff08;五&#xff09;TCAM单元设计 &#x1f508;声明&#xff1a;未经作者允许&#xff0c;禁止转载 &#x1f603;博主主页&#xff1a;王_嘻嘻的CSDN主页 &#x1f511;全新原创以太网交换机项目&#xff0c;Blog内容将聚焦整体架…

核心实验:基于Web前端的性能测试分析!

实验简介 本实验主要利用IE和Chrome的F12开发人员工具结合Web前端测试分析相关知识&#xff0c;对常见网站进行基于前端的性能测试分析&#xff0c;本实验将不会使用到测试开发相关技术&#xff0c;而是纯粹意义上的手工测试&#xff0c;但却是很容易找到系统前端性能及设计问…

C++字体库开发

建议根据字体需求&#xff0c;多个组合使用。高度定制可基于freeTypeharfbuzz基础库完成。 GitHub - GNOME/pango: Read-only mirror of https://gitlab.gnome.org/GNOME/pango GitHub - googlefonts/fontview: Demo app that displays fonts with a free/libre/open-source …

实用软件分享-----一款免费的投屏软件(支持手机投屏到电脑)Aiseesoft Phone Mirror 2.2.36 x64

专栏介绍:本专栏主要分享一些实用的软件(Po Jie版); 声明1:软件不保证时效性;只能保证在写本文时,该软件是可用的;不保证后续时间该软件能一直正常运行;不保证没有bug;如果软件不可用了,我知道后会第一时间在题目上注明(已失效)。介意者请勿订阅。 声明2:本专栏的…

天猫商品列表数据接口(Tmall.item_search)

天猫平台商品列表数据接口&#xff08;taobao.item_search&#xff09;是天猫开放平台提供的一个API接口&#xff0c;用于获取天猫平台上的商品列表数据。通过该接口&#xff0c;用户可以获取到商品的名称、价格、销量、评价等信息。下面将具体介绍这个接口的各个方面&#xff…

H616连接摄像头

&#xff08;1&#xff09;首先将USB摄像头连接到OrangePi开发板的USB接口 &#xff08;2&#xff09;通过lsmod命令查看是否加载了uvcvideo模块 lsmod | grep video &#xff08;3&#xff09;通过 v4l2-ctl 命令可以看到 USB 摄像头的设备节点信息为/dev/video0 sudo apt u…

剖析DeFi交易产品之UniswapV4:创建池子

本文首发于公众号&#xff1a;Keegan小钢 创建池子的底层函数是 PoolManager 合约的 initialize 函数&#xff0c;其代码实现并不复杂&#xff0c;如下所示&#xff1a; function initialize(PoolKey memory key, uint160 sqrtPriceX96, bytes calldata hookData)externalover…

Redis---保证主从节点一致性问题 +与数据库数据保持一致性问题

保证主从节点一致性问题 Redis的同步方式默认是异步的&#xff0c;这种异步的同步方式导致了主从之间的数据存在一定的延迟&#xff0c;因此Redis默认是弱一致性的。 解决&#xff1a; 1.使用Redisson这样的工具&#xff0c;它提供了分布式锁的实现&#xff0c;确保在分布式环…

【C语言】使用C语言编写并使用gcc编译动态链接库

【C语言】使用C 语言编写并使用 gcc 编译动态链接库 1.背景2.使用C编写代码3.使用gcc编译代码1.背景 在windows下开发很多程序接口被封装到动态链接库供其它开发者使用。 本博客使用C语言编写并使用gcc 编译 一个动态链接库文件FpdSys.dll; 然后使用C/C++/C#/Python去调用动态…

代码生成器使用指南,JeecgBoot低代码平台

JeecgBoot 提供强大的代码生成器&#xff0c;让前后端代码一键生成&#xff0c;实现低代码开发。支持单表、树列表、一对多、一对一等数据模型&#xff0c;增删改查功能一键生成&#xff0c;菜单配置直接使用。 同时提供强大模板机制&#xff0c;支持自定义模板&#xff0c;目…

[单master节点k8s部署]15.安全机制

用户访问集群需要认证、授权、准入三个步骤。apiserver是整个集群访问控制的唯一入口。 认证 认证是对用户的身份认证&#xff0c;通常包括用户名密码认证&#xff0c;但是也包括对service account的认证。 限制不同用户访问集群 生成ssl密钥 在/etc/kubernetes/pki/ 目录…

Python 基础 (标准库):heapq (堆)

1. 官方文档 heapq --- 堆队列算法 — Python 3.12.4 文档 2. 相关概念 堆 heap 是一种具体的数据结构&#xff08;concrete data structures&#xff09;&#xff1b;优先级队列 priority queue 是一种抽象的数据结构&#xff08;abstract data structures&#xff09;&…

在非 antd pro 项目中使用 umi OpenAPI

大家好&#xff0c;我是松柏。自从跟着鱼皮哥使用了ant design pro中的OpenAPI插件之后&#xff0c;我已经无法忍受自己写请求后端接口的方法了&#xff0c;所以这篇文章记录一下如何在非ant design pro项目中使用OpenAPI。 安装依赖 首先我们需要安装包umijs/openapi&#x…

上交举办“大模型奥林匹克竞赛”,GPT-4o仅得39分

大模型的奥林匹克竞赛来了&#xff01; 最近&#xff0c;上交构建了一个全面、极具挑战性的奥赛级别的基准——OlympicArena&#xff0c;从来自62个不同奥林匹克竞赛中筛选出11,163个问题&#xff0c;涵盖数学、物理、化学、生物、地理、天文学和计算机科学等七个学科&#xf…

[22] Opencv_CUDA应用之 使用背景相减法进行对象跟踪

Opencv_CUDA应用之 使用背景相减法进行对象跟踪 背景相减法是在一系列视频帧中将前景对象从背景中分离出来的过程&#xff0c;它广泛应用于对象检测和跟踪应用中去除背景 背景相减法分四步进行&#xff1a;图像预处理 -> 背景建模 -> 检测前景 -> 数据验证 预处理去除…

博客搬家前台申请功能下线通知

尊敬的用户们&#xff1a; 您好&#xff01; 感谢您一直以来对我们博客平台的关注与支持。为了更好地优化我们的服务质量和用户体验&#xff0c;经过慎重考虑&#xff0c;我们决定将于近期对博客搬家前台申请功能进行下线处理。在此&#xff0c;我们向广大用户表示诚挚的歉意…

仿论坛项目--第一部分相关习题

1.关于IOC注解&#xff0c;说法正确的是 A.autowired用于注入bean,该注解只能写在成员变量的前面 B.Qualifier用于声明bean的名称&#xff0c;该注解只能引用bean的自定义名称 C.Bean用于装配第三方的Bean&#xff0c;不能装配自定义的bean D.Configuration用于声明配置类&…

AD9026芯片开发实录6-example code

官方发布的软件包中&#xff0c;带了一份example code&#xff0c;用于向客户展示API的调用方法以及基于官方的验证版ADRV902X最简单的bring up的流程。 该 example 位于软件包的路径下&#xff1a;“\Adi.Adrv9025.Api\src\c_src\app\example\”。 代码组成&#xff1a; initd…

JavaScript 实用技巧

1. 使用 const 和 let 替代 var 在 ES6 之前&#xff0c;我们通常使用 var 声明变量。但如今&#xff0c;推荐使用 const 和 let&#xff0c;因为它们具有块级作用域&#xff0c;可以避免很多潜在的问题。 const PI 3.14; // 常量&#xff0c;无法重新赋值 let age 25; // …