完整地实现日期类(分3个文件+测试结果)

🌈完整地实现日期类

👻主要使用了构造函数、运算符重载函数。
👻以下日期类包含接收日期、日期与日期减加减、日期与天数间加减、日期自增减(自动加减一天)、日期间大小比较等功能。

☀️一、分析与优化各函数实现

其实没有必要将所有赋值运算符重载都完整地写出来,有很多函数的实现逻辑其实是有大关联的:

对于日期类的赋值运算符重载,可有以下分组:
①operator== & operator!=;二者可逻辑取反。
②operator+ & operator+= ;一个在另一个基础上。
③operator- & operator-=;一个在另一个基础上。
④operator++ & operator++(int) & operator-- & operator–(int);后置的比前置的多了个整型参数
⑤operator> & operator<= & operator< & operator>=;可以多次逻辑取反。

🎈1.operator== & operator!=

先写==,!=即为==的逻辑取反

//判断是否相等
bool Date::operator==(const Date& d) {return _year == d._year && _month == d._month && _day == d._day;
}
//判断是否不相等
bool Date::operator!=(const Date& d) {return !(*this == d);
}

🎈2.operator> & operator<= & operator< & operator>=

最开始只用写一个函数即可,比如>,剩下的函数都可以复用这个函数了,即:>函数的取反是<=函数;>的结果并上==的结果就得到>=函数;>=函数的取反是<函数。

//判断是否大于
bool Date::operator>(const Date& d) {if (_year > d._year)return true;else if ((_year == d._year) && (_month > d._month)) return true;else if ((_year == d._year) && (_month == d._month)) {if (_day > d._day)return true;}return false;
}
//判断是否小于等于 
bool Date::operator<=(const Date& d) {return !(*this > d);
}
//判断是否大于等于 
bool Date::operator>=(const Date& d) {return *this == d || *this > d;
}
//判断是否小于 
bool Date::operator<(const Date& d) {return !(*this >= d);
}

🎈3.operator+ & operator+=

可以先写+函数,在+函数的基础上复用+函数得到+=函数;也可以先写+=再写+,到底选择哪一种方式呢?选拷贝构造次数少的方式,如下方分析:

🌟(1)先写+=函数,复用+=函数得到+函数
//日期+=天数
Date& Date::operator+=(int x) {if(x<0){return *this-=x;}_day += x;while (_day > GetMonthDay(_year,_month)) {_day -= GetMonthDay(_year,_month);_month++;if (_month > 12) {_month = 1;_year++;}}return *this;
}
//(在+=函数的基础上实现)日期+天数
Date Date::operator+(int x) {Date tmpd(*this);tmpd += x;return tmpd;
}

+=函数中拷贝构造对象次数:0(未涉及拷贝构造对象,且传引用返回,一共拷贝构造了0次)

+=函数中拷贝构造对象次数:2(+在+=的基础上,因此先拷贝复制了0次;之后又拷贝构造了tmpd对象,返回tmpd时用的传值返回,一共拷贝构造了2次)

🌟(2)先写+函数,复用+函数得到+=函数
//日期+天数
Date Date::operator+(int x) {if(x<0){return *this-x;}Date tmpd(*this);tmpd._day += x;while(tmpd._day > GetMonthDay(tmpd._month)) {tmpd._day -= GetMonthDay(tmpd._month);tmpd._month++;if (tmpd._month > 12) {tmpd._month = 1;tmpd._year++;}}return tmpd;}
//(在+函数的基础上实现)日期+=天数
Date& Date::operator+=(int x) {*this = *this + x;return *this;
}

+函数中拷贝构造对象次数:2(用this指针拷贝构造对象、传值返回了类对象,一共拷贝构造了2次)

+=函数中拷贝构造对象次数:3(由于+=在+的基础上,因此先拷贝复制了2次;然后又给this对象赋值了一次,一共拷贝构造了3次)

确定谁复用谁的意义:对于日期类对象,二者拷贝对象次数的差异可能影响不大,但是换一个庞大的类类型,拷贝构造动作会用掉很多空间,会降低效率,因此会产生巨大差异

👻最优方式:先写+=函数,再复用+=函数得到+函数。尽量少地进行拷贝构造动作

🎈4.operator- & operator-=

与+=和+函数同理,最优方式是先写-=函数,再复用-=函数得到-函数。

//日期-=天数=新日期(本身)
Date& Date::operator-=(int x) {if(x<0){return *this+=x;}_day -= x;if (_day > 0) {return *this;}else if (_day == 0) {_month--;if (_month == 0) {_month = 12;_year--;}_day = GetMonthDay(_year,_month);return *this;}else {   //tmp._day<0while (_day < 0) {_month--;_day = GetMonthDay(_year,_month) + _day;if (_day == 0) {_month--;if (_month == 0) {_month = 12;_year--;}_day = GetMonthDay(_year,_month);}}return *this;}
}
//日期-天数=日期(拷贝)
Date Date::operator-(int x) {Date tmp(*this);tmp -= x;return tmp;
}

🎈5.一个特殊的减法重载:日期-日期=天数

对于日期而言,加法这个运算操作一般用于在日期的基础上加天数,得到推算出的日期,很少有两个日期相加的运算;
而减法可以用于日期间天数,得到倒退的日期,还可以日期减日期,得到二者相差多少天

问:是“否日期-日期=天数”的这个重载和operator-重载冲突?
答:不会,因为二者的参数一个是Date类日期对象,另一个是整型数值,返回值一个是整型数值,另一个是Date类日期对象。编译器可以根据函数调用匹配到正确的函数重载。

相减思路:
现有两个日期,需要算出二者间相隔多少天。
1.比较出两个日期中较大的那一个,大的赋值给max对象,小的赋值给min对象;
2.算出大日期是那一年的第几天,记为pass变量;
3.算出小日期距离那一年末还有多少天,记为to变量;
4.得出两日期间相差多少天(算出两日期间完整的年份的天数和,加pass,再加to)

//日期-日期=天数
int Date::operator-(const Date& d) {//1.比较出两个日期中较大的一个Date max(1, 1, 1);Date min(1, 1, 1);if (*this > d) {max = *this;min = d;}else if (*this == d)return 0;else {max = d;min = *this;}//2.算出大日期是那一年的第几天int pass = 0;pass += max._day;for (int i = 1;i < max._month;i++) {pass += GetMonthDay(max._year,i);}//3.算出小日期距离那一年末还有多少天int yearDay = GetYearDay(min._year);int now = 0;for (int i = 1;i < min._month;i++) {now += GetMonthDay(min._year,i);}now += min._day;int to = yearDay - now;//4.得出两日期间相差多少天min._year++;if (min._year > max._year) {int tmp = GetYearDay(max._year);return pass + to - tmp;}int tmp = 0;for (int i = min._year;i < max._year;i++) {tmp += GetYearDay(i);}return pass + to + tmp;
}

🎈6.operator++ & operator++(int) & operator-- & operator–(int)

前置++和后置++的区别(–同理):
(1)前置++表示先++后使用,即变量内的值马上+1,后续使用得到的都是+1后的值;
(2)后置++表示先使用后++,即先使用变量原来的值,使用完后马上+1;
(3)前置++效率更高,因为后置++还需要多一次拷贝。对于内置类型二者差异不大,但对于自定义类型最好用前置,减少拷贝的次数

规定:为了和++d1区分,d1++无参数,而d1++的函数,参数必须为int。

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

☀️二、完整Date类实现和Test、main函数

注意:
1.析构和拷贝构造函数对于日期类而言不用写。
2.分文件时,.cpp文件中存放的函数实现需要指定类域。
3.对于缺省参数,为了防止声明与定义的参数默认值不一致,只能在声明时给出。

🎈1.Date.h头文件

#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
class Date {
private:int _year;int _month;int _day;
public://构造函数Date(int year, int month, int day);//析构函数、拷贝构造函数不用显式写//得到某月的总天数int GetMonthDay(int year, int month)const;//得到某年的总天数int GetYearDay(int year)const;//打印日期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 x);//(在+函数的基础上实现)日期+=天数/*Date& operator+=(int x);*///日期+=天数Date& operator+=(int x);//(在+=函数的基础上实现)日期+天数Date operator+(int x)const;//日期-日期=天数int operator-(const Date& d)const;//日期-=天数=新日期(本身)Date& operator-=(int x);//日期-天数=日期(拷贝)Date operator-(int x)const;//前置++(日期自动+1天)Date& operator++();//后置++(日期自动+1天)Date operator++(int);//前置--(日期自动-1天)Date& operator--();//后置--(日期自动-1天)Date operator--(int);
};

🎈2.Date.cpp函数定义

#include"Date.h"
//构造函数
Date::Date(int year, int month, int day) {_year = year;_month = month;_day = day;//同时完善日期检查功能if (_year < 1 ||_month < 1 || _month > 12 ||_day < 1 || _day > GetMonthDay(_year,_month)){cout << "日期错误" << endl;return;}
}
//得到某月的总天数
int Date::GetMonthDay(int year,int month)const {int arr[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))arr[2] = 29;return arr[month];
}
//得到某年的总天数
int Date::GetYearDay(int year) const {if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))return 366;return 365;
}//打印日期
void Date::Print() const {cout << _year << "年" << _month << "月" << _day << "日" << endl;
}//判断是否相等
bool Date::operator==(const Date& d) const {return _year == d._year && _month == d._month && _day == d._day;
}
//判断是否不相等
bool Date::operator!=(const Date& d) const {return !(*this == d);
}//判断是否大于
bool Date::operator>(const Date& d) const {if (_year > d._year)return true;else if ((_year == d._year) && (_month > d._month)) return true;else if ((_year == d._year) && (_month == d._month)) {if (_day > d._day)return true;}return false;
}
//判断是否小于等于 
bool Date::operator<=(const Date& d) const {return !(*this > d);
}
//判断是否大于等于 
bool Date::operator>=(const Date& d) const {return *this == d || *this > d;
}
//判断是否小于 
bool Date::operator<(const Date& d) const {return !(*this >= d);
}//日期+=天数
Date& Date::operator+=(int x) {_day += x;while (_day > GetMonthDay(_year,_month)) {_day -= GetMonthDay(_year,_month);_month++;if (_month > 12) {_month = 1;_year++;}}return *this;
}
//(在+=函数的基础上实现)日期+天数
Date Date::operator+(int x) const {Date tmpd(*this);tmpd += x;return tmpd;
}//日期-日期=天数
int Date::operator-(const Date& d) const {//1.比较出两个日期中较大的一个Date max(1, 1, 1);Date min(1, 1, 1);if (*this > d) {max = *this;min = d;}else if (*this == d)return 0;else {max = d;min = *this;}//2.算出大日期是哪一月的第几天int pass = 0;pass += max._day;for (int i = 1;i < max._month;i++) {pass += GetMonthDay(max._year,i);}//3.算出小日期距离那一年末还有多少天int yearDay = GetYearDay(min._year);int now = 0;for (int i = 1;i < min._month;i++) {now += GetMonthDay(min._year,i);}now += min._day;int to = yearDay - now;//4.得出两日期间相差多少天min._year++;if (min._year > max._year) {int tmp = GetYearDay(max._year);return pass + to - tmp;}int tmp = 0;for (int i = min._year;i < max._year;i++) {tmp += GetYearDay(i);}return pass + to + tmp;
}//日期-=天数=新日期(本身)
Date& Date::operator-=(int x) {_day -= x;if (_day > 0) {return *this;}else if (_day == 0) {_month--;if (_month == 0) {_month = 12;_year--;}_day = GetMonthDay(_year,_month);return *this;}else {   //tmp._day<0while (_day < 0) {_month--;_day = GetMonthDay(_year,_month) + _day;if (_day == 0) {_month--;if (_month == 0) {_month = 12;_year--;}_day = GetMonthDay(_year,_month);}}return *this;}
}
//日期-天数=日期(拷贝)
Date Date::operator-(int x) const {Date tmp(*this);tmp -= x;return tmp;
}//前置++(日期自动+1天)
Date& Date::operator++() {*this += 1;return *this;
}
//后置++(日期自动+1天)
Date Date::operator++(int) {Date tmp(*this);*this += 1;return tmp;
}//前置--(日期自动-1天)
Date& Date::operator--() {*this -= 1;return *this;
}
//后置--(日期自动-1天)
Date Date::operator--(int) {Date tmp(*this);*this -= 1;return tmp;
}

🎈3.Test.cpp测试

#include"Date.h"
int main() {Date d1(2024, 1, 31);Date d2(2000, 2, 12);Date d3(d1);int flag = 0;//测试==和!=if (d1 == d2)flag = 1;if (d1 != d2)flag = 2;cout << flag << endl;   //2//测试>、<if (d1 > d2)flag = 3;if (d1 <= d2)flag = 4;cout << flag << endl;   //3//测试>=、<=if (d1 >= d3)flag = 5;if (d1 < d3)flag = 6;cout << flag << endl;   //5//计算+、+=Date a = d2 + 5;a.Print();   //2000年2月17日Date b = d2 + 55;b.Print();   //2000年4月7日d2.Print();  //2000年2月12日d2 += 5;d2.Print();  //2020年2月17日d2 += 55;    d2.Print();  //2020年4月12日//计算-、-=Date c = d2 - 55;c.Print();   //2000年2月17日Date d = d2 - 5;d.Print();   //2000年4月7日d2.Print();  //2020年4月12日d2 -= 55;d2.Print();  //2000年2月17日d2 -= 5;d2.Print();  //2000年2月12日//计算两日期相隔多少天int x = d1 - d2;cout << x << endl;   //8754//测试前置++、后置++Date tmp1(d2++);tmp1.Print();  //2000年2月12日d2.Print();    //2000年2月13日Date tmp2(++d2);tmp2.Print();  //2000年2月14日d2.Print();    //2000年2月14日//测试前置--、后置--Date tmp3(d2--);tmp3.Print();  //2000年2月14日d2.Print();    //2000年2月13日Date tmp4(--d2);tmp4.Print();  //2000年2月12日d2.Print();    //2000年2月12日
}

🎈测试结果

经验证,是正确的。
在这里插入图片描述

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

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

相关文章

【论文复现】Conditional Generative Adversarial Nets(CGAN)

文章目录 GAN基础理论2.1 算法来源2.2 算法介绍2.3 基于CGAN的手写数字生成实验2.3.1 网络结构2.3.2 训练过程一、 D的loss (discriminator_train_step)二、 G的loss (generator_train_step) 2.4 实验分析2.4.1 超参数调整一、batch size二、 epochs三、 Adam&#xff1a;learn…

java+springboot企业员工工作日志审批管理系统ssm+vue

企业OA管理系统具有管理员角色&#xff0c;用户角色&#xff0c;这两个操作权限。 ①管理员 管理员在企业OA管理系统里面查看并管理人事信息&#xff0c;工作审批信息&#xff0c;部门信息&#xff0c;通知公告信息以及内部邮件信息。 管理员功能结构图如下&#xff1a; ide工具…

isctf---web

圣杯战争 php反序列 ?payloadO:6:"summon":2:{s:5:"Saber";O:8:"artifact":2:{s:10:"excalibuer";O:7:"prepare":1:{s:7:"release";O:5:"saber":1:{s:6:"weapon";s:52:"php://filter…

1 月 30 日算法练习-思维和贪心

文章目录 重复字符串翻硬币乘积最大 重复字符串 思路&#xff1a;判断是否能整除&#xff0c;如果不能整除直接退出&#xff0c;能整除每次从每组对应位置中找出出现最多的字母将其他值修改为它&#xff0c;所有修改次数即为答案。 #include<iostream> using namespace …

【JS逆向实战-入门篇】某gov网站加密参数分析与Python算法还原

文章目录 1. 写在前面2. 请求分析3. 断点分析4. 算法还原 【作者主页】&#xff1a;吴秋霖 【作者介绍】&#xff1a;Python领域优质创作者、阿里云博客专家、华为云享专家。长期致力于Python与爬虫领域研究与开发工作&#xff01; 【作者推荐】&#xff1a;对JS逆向感兴趣的朋…

如何对Ajax请求进行封装操作,解决跨域问题的方法,如何使用core解决跨域

目录 1.Ajax原理 2.为什么要封装 3.如何进行封装 4.如何请求 5.如何解决Ajax跨域问题 6.使用CORS解决Ajax跨域问题 1.服务端 2.客户端 1.Ajax原理 Ajax&#xff08;Asynchronous JavaScript and XML&#xff09;是一种通过在后台与服务器进行少量数据交换&…

微信小程序(二十八)网络请求数据进行列表渲染

注释很详细&#xff0c;直接上代码 上一篇 新增内容&#xff1a; 1.GET请求的规范 2.数据赋值的方法 源码&#xff1a; index.wxml <!-- 列表渲染基础写法&#xff0c;不明白的看上一篇 --> <view class"students"><view class"item">&…

Shell脚本之 -------------免交互操作

一、Here Document 1.Here Document概述 Here Document 使用I/O重定向的方式将命令列表提供给交互式程序 Here Document 是标准输 入的一种替代品&#xff0c;可以帮助脚本开发人员不必使用临时文件来构建输入信息&#xff0c;而是直接就地 生产出一个文件并用作命令的标准…

排序链表---归并--链表OJ

https://leetcode.cn/problems/sort-list/submissions/499363940/?envTypestudy-plan-v2&envIdtop-100-liked 这里我们直接进阶&#xff0c;用时间复杂度O(nlogn)&#xff0c;空间复杂度O(1)&#xff0c;来解决。 对于归并&#xff0c;如果自上而下的话&#xff0c;空间复…

Netty源码二:服务端创建NioEventLoopGroup

示例 还是拿之前启动源码的示例&#xff0c;来分析NioEventLoopGroup源码 NioEventLoopGroup构造函数 这里能看到会调到父类的MultiThread EventLoopGroup的构造方法 MultiThreadEventLoopGroup 这里我们能看到&#xff0c;如果传入的线程数目为0&#xff0c;那么就会设置2倍…

代码随想录 Leetcode222.完全二叉树的节点个数

题目&#xff1a; 代码&#xff08;首刷自解 2024年1月30日&#xff09;&#xff1a; class Solution { public:int countNodes(TreeNode* root) {int res 0;if (root nullptr) return res;queue<TreeNode*> deque;TreeNode* cur root;deque.push(cur);int size 0;w…

网络隔离场景下访问 Pod 网络

接着上文 VPC网络架构下的网络上数据采集 介绍 考虑一个监控系统&#xff0c;它的数据采集 Agent 是以 daemonset 形式运行在物理机上的&#xff0c;它需要采集 Pod 的各种监控信息。现在很流行的一个监控信息是通过 Prometheus 提供指标信息。 一般来说&#xff0c;daemonset …