【C++语言】Date类的代码实现(操作符重载运用)

在这里插入图片描述


文章目录

  • 前言
  • Date类的构思
  • Date类的相关实现
    • 基本框架(默认成员函数)
    • 计算n天前\后的日期
    • 补充:前置++、后置++说明
    • 判断两个日期的关系(大于,小于等);
    • 可以计算两个日期之间相差多少天
    • 补充:流输入以及流提取操作符实现:
  • 总结
  • C++语言系列学习目录


前言

在上一章节中,我们学习了类和对象的一些内容,包括:类的相关特征、类的默认成员函数、以及操作符重载(重点)。本节就综合前面的相关内容,实现一个Date类。


Date类的构思

我们设想的Date类包括以下操作:

  1. 可以计算n天前\后的日期(+、-、+=、-=等);
  2. 判断两个日期的关系(大于,小于等);
  3. 可以计算两个日期之间相差多少天;

Date类的相关实现

基本框架(默认成员函数)

因为Date类型比较简单,属性只有内置类型,所以大部分默认成员函数就可以满足需求。

class Date
{
public://构造函数:全缺省的默认构造函数,但需要判断合法性,所以需要自己定义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;assert(false);}}//拷贝构造函数:Date类属性全是内置类型,可以不写拷贝构造//赋值运算符重载:Date类属性全是内置类型,赋值运算符重载也可以不用写//析构函数:Date类属性全是内置类型,赋值运算符重载也不用写
private:int _year;int _month;int _day;
};

计算n天前\后的日期

计算n天后基本思路:
日期加上天数,天数相加,判断是否超出当月的日期天数(循环判断),若超出,则月数进1,同时判断月数是否等于13,若等于则再向年进1,月变回1月;

设计流程:

  1. GetMonthDay()获得当月的天数;
  2. Date Date::operator # (int day) const (#代表多种运算符重载);

1.GetMonthDay()
功能:传入年和月,得出该月的天数。
参数:(int year, int month)
返回:int (天数)

注意:方法一般设置在头文件之外,头文件(Date.h)声明函数方法,(Date.cpp)实现方法,因此方法前需要加入Date::类域

int Date::GetMonthDay(int year, int month)
{//静态设置每月天数,二月需要判断是否为闰年得出//之所以静态,是减少频繁创造过程的损失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];}
}
  1. Date Date::operator+=(int day) (+=运算符重载);
    功能:实现Date类和int整形相加,并且直接修改该对象;
    参数: (int day)
    返回: Date&
Date& Date::operator+=(int day)
{if (day < 0) //考虑我们输入的day是负数{return *this -= -day;}_day += day;while (_day > GetMonthDay(_year, _month)){_day -= GetMonthDay(_year, _month);++_month;if (_month == 13){++_year;_month = 1;}}return *this;
}
  1. Date Date::operator+(int day) const (+运算符重载);
    功能:实现Date类和int整形相加,返回最终日期。
    参数: (int day)
    返回: Date (最终日期)
Date Date::operator+(int day)  const
{//直接复用+=号Date tmp(*this);tmp += day;return tmp;
}

计算n天前基本思路:
日期减去天数,天数相减,判断天数是否为负数或者零(循环判断),若为负数,则月数减1,同时判断月数是否等于0,若等于则再向年借1,月变回12月;

  1. Date& Date::operator-=(int day) (-=运算符重载)
    功能:实现Date类和int整形相减,且直接修改该对象。
    参数: (int day)
    返回: Date&
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);}return *this;
}
  1. Date Date::operator-(int day) const (-运算符重载)
    功能:实现Date类和int整形相减,返回最终日期。
    参数: (int day)
    返回: Date
Date Date::operator-(int day) const
{Date tmp = *this;tmp -= day;return tmp;
}

补充:前置++、后置++说明

前置++,返回++后的值,实现时返回原本对象即可,所以可以引用返回
后置++,返回++前的值,需要创建临时变量储存,临时变量出函数自动销毁,所以只能传值返回

但我们运算符重载的时候发现,他们都以Date& operator++()为声明,这会导致编译器无法区分,从而报错。从而为了区别,C++这样规定:
前置++声明:Date& operator++();
后置++声明:Date operator++(int);
为区分他们,在后置++的传参部分加入(int)int占位,以示区分,并没有其他作用。

代码实现很简单,但必须认识到这点(减减一并实现):

// 前置++
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;
}

判断两个日期的关系(大于,小于等);

我们需要先判断两个日期的大小关系,才可以实现两个日期的相减;
大小关系操作数我们通常只需要实现两个最基本的,其他复用就可以了:大于或者小于,以及等于。

bool operator<(const Date& x) const
功能:判断两个日期的大小,该对象是否小于x对象;
参数:(const Date& x)
返回值: bool 布尔类型

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;}return false;
}bool Date::operator==(const Date& x) const
{return _year == x._year&& _month == x._month&& _day == x._day;
}// 复用
// d1 <= d2
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);
}bool Date::operator!=(const Date& x) const
{return !(*this == x);
}

可以计算两个日期之间相差多少天

基本思路:用最简单的思路,一天一天计算。判断并找出谁大谁小,用小的日期不断++,++过程中用临时变量计数,直到小的日期等于大的日期结束。

int Date::operator-(const Date& d) const
功能:计算两个日期之间相差多少天
参数:(const Date& d)
返回值: int (相差天数)

int Date::operator-(const Date& d) const
{
//假设法:任意假设大小;Date max = *this;Date min = d;int flag = 1;//巧妙运用1和-1if (*this < d){max = d;min = *this;flag = -1;}int n = 0;while (min != max){++min;++n;}return n * flag;
}

补充:流输入以及流提取操作符实现:

这里我们只是简单认识其中的一些问题即可,内容实现需要i/o相关库的基础,不容易懂。

  1. <<(>>) 流输入(流提取)他们无法在类域中实现,因为我们在使用cout和cin的过程中,第一参数并不是我们的Date(或其他类对象)而是cout和cin,所以我们需要定义为类外的函数方法;
  2. 我们要实现连续输入或输出,所以返回参数应当是ostream&或istream&;
  3. 外部定义实现的函数无法访问类中private的属性,因此需要类有相关方法或者设置该外部定义为友元函数;
class Date
{// 友元函数声明friend ostream& operator<<(ostream& out, const Date& d);friend istream& operator>>(istream& in, Date& d);...其他代码
}

代码实现:

ostream& operator<<(ostream& out, const Date& d)
{out << d._year << "年" << d._month << "月" << d._day << "日" << endl;return out;
}istream& operator>>(istream& in, Date& d)
{int year, month, day;in >> year >> month >> day;if (month > 0 && month < 13&& day > 0 && day <= d.GetMonthDay(year, month)){d._year = year;d._month = month;d._day = day;}else{cout << "非法日期" << endl;assert(false);}return in;
}

完整代码如下:

Date.h

#pragma once
#include<iostream>
#include<assert.h>
using namespace std;class Date
{// 友元函数声明friend ostream& operator<<(ostream& out, const Date& d);friend istream& operator>>(istream& in, Date& d);
public:Date(int year = 1, int month = 1, int day = 1);void Print() const{cout << _year << "-" << _month << "-" << _day << endl;}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 GetMonthDay(int year, int month);// d1 + 100Date& 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& d) const;private:int _year;int _month;int _day;
};ostream& operator<<(ostream& out, const Date& d);
istream& operator>>(istream& in, Date& d);

Date.cpp

#include "Date.h"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;assert(false);}
}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;}return false;
}bool Date::operator==(const Date& x) const
{return _year == x._year&& _month == x._month&& _day == x._day;
}// 复用
// d1 <= d2
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);
}bool Date::operator!=(const Date& x) const
{return !(*this == x);
}int Date::GetMonthDay(int year, int month)
{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];}
}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;
}// d1 + 100
Date Date::operator+(int day)  const
{Date tmp(*this);tmp += day;return tmp;/*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;*/
}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);}return *this;
}Date Date::operator-(int day) const
{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;
}// d1 - d2;
int Date::operator-(const Date& d) const
{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;
}ostream& operator<<(ostream& out, const Date& d)
{out << d._year << "年" << d._month << "月" << d._day << "日" << endl;return out;
}istream& operator>>(istream& in, Date& d)
{int year, month, day;in >> year >> month >> day;if (month > 0 && month < 13&& day > 0 && day <= d.GetMonthDay(year, month)){d._year = year;d._month = month;d._day = day;}else{cout << "非法日期" << endl;assert(false);}return in;
}

总结

本节重点是实践各种操作符的重载,以简单Date类做案例。


C++语言系列学习目录

提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加,添加超链接

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

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

相关文章

SQLI-labs-第十三关和第十四关

目录 第十三关 1、判断注入点 2、判断当前数据库 3、爆表名 4、爆字段名 5、爆值 第十四关 1、判断注入点 知识点&#xff1a;POST方式的单引号和括号闭合错误,报错注入 第十三关 思路&#xff1a; 1、判断注入点 使用Burpsuite抓包 首先加入一个单引号&#xff0c;…

Linux vscode push报错fatal: Authentication failed

注意啊&#xff0c;Git基于密码的身份验证已经被删除了&#xff0c;所以这个报错发生时无论密码正确与否&#xff0c;以及参考比较旧的改bug教程&#xff0c;都没法提交。进入提示的网址&#xff0c;生成个人访问令牌就好了

Java解决垂直鉴权问题(对垂直权限进行校验)

Java解决垂直鉴权问题&#xff08;对垂直权限进行校验&#xff09; 文章目录 Java解决垂直鉴权问题&#xff08;对垂直权限进行校验&#xff09;前言一、垂直鉴权是什么&#xff1f;二、实现过程1.新建接口权限菜单映射表2.项目初始化时加载接口菜单映射关系3.自定义过滤器拦截…

淘宝电商商家ERP订单接口接入指南:对接ERP与淘宝系统的数据桥梁

最近几年&#xff0c;电商发展如火如荼&#xff0c;一方面互联网企业在推互联网 和O2O&#xff0c;同时很多传统企业也在积极互联网&#xff0c;通过各种电商平台拓展销售渠道&#xff0c;有些还同时建有自建的电商平台。这些电商平台通常下单&#xff0c;结算&#xff0c;促销…

大数据技术原理与技术简答

1、HDFS中名称节点的启动过程 名称节点在启动时&#xff0c;会将FsImage 的内容加载到内存当中&#xff0c;此时fsimage是上上次关机时的状态。然后执行 EditLog 文件中的各项操作&#xff0c;使内存中的元数据保持最新。接着创建一个新的FsImage 文件和一个空的 Editlog 文件…

封装Springboot基础框架功能-03

在些模块中汇总了一些web开发常用的配置和功能。 模块源码结构 Restful API常用定义 QueryParam请求参数 Data public class QueryParam {private String key;private String value; }RestfulController实现 RestfulController.java&#xff0c;主要汇总一些常用的restful的…

Bugku Crypto 部分题目简单题解(三)

where is flag 5 下载打开附件 Gx8EAA8SCBIfHQARCxMUHwsAHRwRHh8BEQwaFBQfGwMYCBYRHx4SBRQdGR8HAQ0QFQ 看着像base64解码 尝试后发现&#xff0c;使用在线工具无法解密 编写脚本 import base64enc Gx8EAA8SCBIfHQARCxMUHwsAHRwRHh8BEQwaFBQfGwMYCBYRHx4SBRQdGR8HAQ0QFQ tex…

科技云报道:从亚运到奥运,大型国际赛事共赴“云端”

科技云报道原创。 “广播电视转播技术拯救了奥运会”前奥委会主席萨马兰奇这句话广为流传。 奥运会、世界杯、亚运会这样的全球大型体育赛事不仅是体育竞技的盛宴&#xff0c;也是商业盛宴&#xff0c;还是技术与人文的融合秀。随着科技的进步&#xff0c;技术在体育赛事中扮…

【算法系列】字符串

目录 leetcode题目 一、最长公共前缀 二、最长回文子串 三、二进制求和 四、字符串相加 五、字符串相乘 六、仅仅反转字母 七、字符串最后一个单词的长度 八、验证回文串 九、反转字符串 十、反转字符串 II 十一、反转字符串中的单词 III leetcode题目 一、最长公…

【漏洞复现】某小日子太阳能系统DataCube3审计

漏洞描述 某小日子太阳能系统DataCube3终端测量系统 多个漏洞利用方式 免责声明 技术文章仅供参考,任何个人和组织使用网络应当遵守宪法法律,遵守公共秩序,尊重社会公德,不得利用网络从事危害国家安全、荣誉和利益,未经授权请勿利用文章中的技术资料对任何计算机系统进…

【Shell脚本】Shell编程之循环语句

目录 一.循环语句 1.for语句的结构 1.1.格式 1.2.实操案例 案例1. 案例2. 案例3. 案例4. 2.while语句的结构 2.1.格式 2.2.实操案例 案例1. 案例2. 案例3. 案例4. 3.until循环命令 3.1.格式 3.2.实操案例 案例1. 二.补充 1.常用转义符 一.循环语句 1.for…

从零入门激光SLAM(十三)——LeGo-LOAM源码超详细解析4

大家好呀&#xff0c;我是一个SLAM方向的在读博士&#xff0c;深知SLAM学习过程一路走来的坎坷&#xff0c;也十分感谢各位大佬的优质文章和源码。随着知识的越来越多&#xff0c;越来越细&#xff0c;我准备整理一个自己的激光SLAM学习笔记专栏&#xff0c;从0带大家快速上手激…

RAG 场景对Milvus Cloud向量数据库的需求

虽然向量数据库成为了检索的重要方式,但随着 RAG 应用的深入以及人们对高质量回答的需求,检索引擎依旧面临着诸多挑战。这里以一个最基础的 RAG 构建流程为例:检索器的组成包括了语料的预处理如切分、数据清洗、embedding 入库等,然后是索引的构建和管理,最后是通过 vecto…

网络编程--tcp三次握手四次挥手

1、三次握手 &#xff08;1&#xff09;三次握手的详述 首先Client端发送连接请求报文&#xff0c;Server段接受连接后回复ACK报文&#xff0c;并为这次连接分配资源。Client端接收到ACK报文后也向Server段发生ACK报文&#xff0c;并分配资源&#xff0c;这样TCP连接就建立了。…

【计算机毕业设计】springboot海洋馆预约系统的设计与实现

海洋馆预约系统采用B/S架构&#xff0c;数据库是MySQL。网站的搭建与开发采用了先进的java进行编写&#xff0c;使用了 springboot框架。该系统从两个对象&#xff1a;由管理员和用户来对系统进行设计构建。主要功能包括&#xff1a;个人信息修改&#xff0c;对用户、门票信息、…

好景盒式磁带随声听

少年时代柜子里翻出来的磁带录音机电路板 两颗芯片&#xff0c;FM芯片&#xff0c;电机驱动 CD9088CBD6650

仿“今日头条”新闻系统源码

伴随着移动互联网的热潮和自媒体时代的到来&#xff0c;因此我们看到了以“今日头条、抖音、快手、小红书”等为代表的自媒体平台的崛起。这种新的信息传播方式给广大用户带来获取资讯的便利&#xff0c;也给每个人的思想和生活带来了潜移默化的影响。随着时代发展和进步&#…

【记录】常见的前端设计系统(Design System)

解释一下设计系统的定义&#xff0c;以及在国内&#xff0c;都有那些优秀的设计系统可以学习&#xff0c;希望可以帮到大家。 什么是设计系统&#xff08;Design System)&#xff1f; 设计系统&#xff08;Design System&#xff09;是一套综合性的指导原则、组件和规则&…

C补充1—1章1.0—C程序语言设计(许宝文,李志)

二手书到了&#xff0c;好消息&#xff0c;前主人看的很认真&#xff0c;坏消息&#xff0c;只看到这页了 啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊最后几题好难啊啊啊啊啊&#xff0c;再议 目录 1.1 入门 1.2 变量与算数表达式 练习1-3 //打印温度对照表 练习1-4 //摄氏-华氏温…

Linux(CentOS7)离线使用安装盘部署Telnet

[在线工具网 - 各类免费AI工具合集&#xff0c;免费pdf转word等](https://www.orcc.online) https://orcc.online 挂载镜像CentOS-7-x86_64-DVD-1810.iso到/mnt下&#xff08;其他位置也行&#xff09;&#xff0c;命令如下&#xff1a; mount /dev/sr0 /mnt 安装包默认在Pa…