【C++】:拷贝构造函数与赋值运算符重载的实例应用之日期类的实现

在这里插入图片描述

C++实现日期类
├─属性:
│  ├─年份
│  ├─月份
│  └─日期
├─方法:
│  ├─构造函数
│  ├─拷贝构造函数
│  ├─析构函数
│  ├─设置年份
│  ├─设置月份
│  ├─设置日期
│  ├─获取年份
│  ├─获取月份
│  ├─获取日期
│  ├─判断是否为闰年
│  ├─计算该日期是该年的第几天
│  ├─计算该日期是星期几
│  └─重载运算符(+-==!=<><=>=

一、📚头文件的声明(Date.h)

🔑日期类的实现,将按以下声明依次进行,其中因为Print函数比较短,直接放到类里面让其变成内联函数

#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();int GetMonthDay(int year, int month);bool operator==(const Date& y);bool operator!=(const Date& y);bool operator>(const Date& y);bool operator<(const Date& y);bool operator>=(const Date& y);bool operator<=(const Date& y);int operator-(const Date& d);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);
private:int _year;int _month;int _day;
};
class Date
{
public:// 获取某年某月的天数int GetMonthDay(int year, int month){static int days[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 
31};int day = days[month];if (month == 2&&((year % 4 == 0 && year % 100 != 0) || (year%400 == 0))){day += 1;}return day;}// 全缺省的构造函数Date(int year = 1900, int month = 1, int day = 1);// 拷贝构造函数// d2(d1)Date(const Date& d);// 赋值运算符重载// d2 = d3 -> d2.operator=(&d2, d3)Date& operator=(const Date& d);// 析构函数~Date();// 日期+=天数Date& operator+=(int day);// 日期+天数Date operator+(int day);// 日期-天数Date operator-(int day);// 日期-=天数Date& operator-=(int day);// 前置++Date& operator++();// 后置++Date operator++(int);// 后置--Date operator--(int);// 前置--Date& operator--();// >运算符重载bool operator>(const Date& d);// ==运算符重载bool operator==(const Date& d);// >=运算符重载bool operator >= (const Date& d);// <运算符重载bool operator < (const Date& d);// <=运算符重载bool operator <= (const Date& d);// !=运算符重载bool operator != (const Date& d);// 日期-日期 返回天数int operator-(const Date& d);
private:int _year;int _month;int _day;
};

二、📚获取天数的函数

🔑而我们实现日期类经常要用到某月有多少天,在这里先把获得某月有多少天的函数实现出来。实现时先检查传参有没有问题,在注意把数组设置成静态的,出了作用域还能访问,就不需要考虑每次调用函数建立栈帧后重新给数组分配空间的事情了,因为数组一直被存放在静态区 其次我们先判断这个月是不是二月份,避免判断某年是平年还是闰年一大堆操作后,发现月份不是二月份

int Date::GetMonthDay(int year, int month)
{assert(year >= 1 && month >= 1 && month <= 12);static int monthArray[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;return monthArray[month];
}

三、📚Date的默认成员函数

🔑1.编译器默认生成的构造函数不会处理内置类型,所以我们需要自己去写构造函数,推荐全缺省的构造函数,编译器对自定义类型会自动调用该类型的默认构造
🔑2.由于Date类的成员变量都是内置类型,所以析构函数不需要我们自己写,因为没有资源的申请。并且拷贝构造和赋值重载也不需要写,因为Date类不涉及深拷贝的问题,仅仅使用浅拷贝就够了

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)){//assert(false);Print();cout << "日期非法" << endl;}
}

🔑用一个类初始化另外一个类

Date::Date(const Date& d)
{_year = d._year;_month = d._month;_day = d._day;
}

四、📚日期类的大小比较

🔑由于日期类的大小比较,均不涉及对自身的改变,对此,我们统一用const来修饰this指针,让其变成const成员函数,减少代码的出错性

五、📚>运算符重载

🔑在这里我们找出所有日期a大于日期b的情况 第一种:年比年大 第二种:年相同 月比月大 第三种:年和月都相同 日比日大 再依次向下写就完成了>的比较

bool Date::operator>(const Date& y)
{if (_year > y._year){return true;}else if (_year == y._year && _month > y._month){return true;}else if (_year == y._year && _month == y._month && _day > y._day){return true;}return false;
}

六、📚==运算符重载

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

七、📚>= < <= !=对> ==的复用

// d1 != d2
bool Date::operator!=(const Date& y)
{return !(*this == y);
}bool Date::operator>(const Date& y)
{if (_year > y._year){return true;}else if (_year == y._year && _month > y._month){return true;}else if (_year == y._year && _month == y._month && _day > y._day){return true;}return false;
}bool Date::operator>=(const Date& y)
{return *this > y || *this == y;
}bool Date::operator<(const Date& y)
{return !(*this >= y);
}bool Date::operator<=(const Date& y)
{return !(*this > y);
}

八、📚日期类的计算

🔑日期类的连续赋值
在内置类型的适合我们经常有连续赋值的习惯,类似a1=a2=a3这种,而日期类也支持连续赋值的操作对此我们返回值不能写void 而应该返回引用,我们可以减少拷贝,从而提高效率 这是一名C/C++程序员的基本素养

Date& Date::operator=(const Date& d)
{this->_year = d._year;this->_month = d._month;this->_day = d._day;return *this;
}

🔑日期类的加法
+=运算符重载和+对+=的复用
🔑+=实现的思路就是,实现一个循环,直到天数回到该月的正常天数为止,在循环内部要做的就是进月和进年,让天数不断减去本月天数,直到恢复本月正常天数时,循环结束,返回对象本身即可

// d1 += 100
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;return tmp;
}

🔑-=实现的思路就是,实现一个循环,直到天数变为正数为止,在循环内部要做的就是借月和借年,让天数不断加上上一个月份的天数,直到恢复正数为止,循环结束,返回对象本身

Date& Date::operator-=(int day)
{if (day < 0){return *this += (-day);}_day -= day;while (_day <= 0){--_month;if (_month == 0){--_year;_month = 12;}_day += GetMonthDay(_year, _month);}return *this;
}Date Date::operator-(int day)
{Date tmp(*this);tmp -= day;return tmp;
}

🔑前置++和后置++重载
后置++比前置++多一个参数int 同时后置返回的临时变量 不能添加引用 同时两个this都被改变了 不加const修饰

++d1;
d1.operator++();
d1.Print();d1++;
d1.operator++(10);
d1.operator++(1);
d1.Print();
// ++d1
Date& Date::operator++()
{*this += 1;return *this;
}// d1++
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;
}

九、📚日期−日期重载

🔑日期类相减不需要日期本身,因此用const修饰。由于采用运算法求日期减去日期比较麻烦 还好考虑差有几年 几月 甚至几月中是否包括二月 所以在这样我们采用小日期自增的方式实现 用一个变量n记录

// d1 - d2
int Date::operator-(const Date& d)
{// 假设左大右小int flag = 1;Date max = *this;Date min = d;// 假设错了,左小右大if (*this < d){max = d;min = *this;flag = -1;}int n = 0;while (min != max){++min;++n;}return n * flag;
}

十、📚日期类实现总代码

#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)){//assert(false);Print();cout << "日期非法" << endl;}
}void Date::Print()
{cout << _year << "/" << _month << "/" << _day << endl;
}bool Date::operator==(const Date& y)
{return _year == y._year&& _month == y._month&& _day == y._day;
}// d1 != d2
bool Date::operator!=(const Date& y)
{return !(*this == y);
}bool Date::operator>(const Date& y)
{if (_year > y._year){return true;}else if (_year == y._year && _month > y._month){return true;}else if (_year == y._year && _month == y._month && _day > y._day){return true;}return false;
}bool Date::operator>=(const Date& y)
{return *this > y || *this == y;
}bool Date::operator<(const Date& y)
{return !(*this >= y);
}bool Date::operator<=(const Date& y)
{return !(*this > y);
}int Date::GetMonthDay(int year, int month)
{assert(year >= 1 && month >= 1 && month <= 12);int monthArray[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;return monthArray[month];
}// d1 += 100
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;return tmp;
}
// 
// d1 += 100
//Date& Date::operator+=(int day)
//{
//	//Date d = *this + day;
//	//*this = d;
//
//	*this = *this + day;
//	return *this;
//}
//
//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;
//		}
//	}
//
//	return tmp;
//}Date& Date::operator-=(int day)
{if (day < 0){return *this += (-day);}_day -= day;while (_day <= 0){--_month;if (_month == 0){--_year;_month = 12;}_day += GetMonthDay(_year, _month);}return *this;
}Date Date::operator-(int day)
{Date tmp(*this);tmp -= day;return tmp;
}// 21:13继续
// ++d1
Date& Date::operator++()
{*this += 1;return *this;
}// d1++
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)
{// 假设左大右小int flag = 1;Date max = *this;Date min = d;// 假设错了,左小右大if (*this < d){max = d;min = *this;flag = -1;}int n = 0;while (min != max){++min;++n;}return n * flag;
}
#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();int GetMonthDay(int year, int month);bool operator==(const Date& y);bool operator!=(const Date& y);bool operator>(const Date& y);bool operator<(const Date& y);bool operator>=(const Date& y);bool operator<=(const Date& y);int operator-(const Date& d);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);
private:int _year;int _month;int _day;
};
#include "Date.h"void TestDate1()
{Date d1(2023, 10, 24);d1.Print();Date ret1 = d1 - 100;ret1.Print();Date ret2 = d1 - 10000;ret2.Print();Date ret3 = d1 + 100;ret3.Print();Date ret4 = d1 + 10000;ret4.Print();
}void TestDate2()
{Date d1(2023, 10, 24);d1.Print();// 语法设计,无法逻辑闭环,那么这时就只能特殊处理// 特殊处理++d1;d1.operator++();d1.Print();d1++;d1.operator++(10);d1.operator++(1);d1.Print();
}void TestDate3()
{Date d1(2023, 10, 24);d1.Print();Date d2(2024, 5, 5);d2.Print();Date d3(2024, 8, 1); d3.Print();cout << d2 - d1 << endl;cout << d1 - d3 << endl;}void TestDate4()
{Date d1(2023, 10, 24);d1 += -100;d1.Print();
}int main()
{TestDate4();return 0;
}

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

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

相关文章

websocket和mqtt

WebSocket是一种通信协议&#xff0c;它允许在浏览器和服务器之间建立持久连接&#xff0c;并允许双向传递数据。MQTT则是一种轻量级的发布/订阅消息传输协议&#xff0c;常用于物联网(IoT)设备之间的通信。 &#xff08;1&#xff09;js能直接实现mqtt吗&#xff0c;还是需…

已解决java.lang.IllegalStateException: Duplicate key

已解决java.lang.IllegalStateException: Duplicate key 文章目录 报错问题解决思路解决方法交流 报错问题 java.lang.IllegalStateException: Duplicate key 解决思路 java.lang.IllegalStateException: Duplicate key 是由于在使用 Map 或 Set 时&#xff0c;试图将一个已经…

十、sdl显示yuv图片

前言 SDL中内置加载BMP的API&#xff0c;使用起来会更加简单&#xff0c;便于初学者学习使用SDL 如果需要加载JPG、PNG等其他格式的图片&#xff0c;可以使用第三方库&#xff1a;SDL_image 测试环境&#xff1a; ffmpeg的4.3.2自行编译版本windows环境qt5.12sdl2.0.22&…

redis的性能管理和雪崩

redis的性能管理 redis的数据是缓存在内存当中的 系统巡检&#xff1a; 硬件巡检、数据库、nginx、redis、docker、k8s 运维人员必须要关注的redis指标 在日常巡检中需要经常查看这些指标使用情况 info memory #查看redis使用内存的指标 used_memory:11285512 #数据占用的…

最简单的简历练习

代码&#xff1a; <!DOCTYPE html> <html> <head> <title>我的简历</title> <style> body { background-image: url(https://picsum.photos/id/1018/1000/1000); background-size: cover; …

已解决java.lang.RuntimeException: java.io.IOException: invalid constant type: 18异常的正确解决方法,亲测有效!!!

已解决java.lang.RuntimeException: java.io.IOException: invalid constant type: 18异常的正确解决方法&#xff0c;亲测有效&#xff01;&#xff01;&#xff01; 文章目录 报错问题解决方法交流 报错问题 java.lang.RuntimeException: java.io.IOException: invalid cons…

完美解决ERROR: Command errored out with exit status 1: command: ‘f:\program files\python\python36\pyt

完美解决ERROR: Command errored out with exit status 1: command: f:\program files\python\python36\pyt 下滑查看解决方法 文章目录 报错问题解决思路解决方法交流 报错问题 ERROR: Command errored out with exit status 1: command: ‘f:\program files\python\python3…

【华为OD】C卷真题 100%通过:攀登者1 C/C++源码实现

【华为OD】C卷真题 100%通过&#xff1a;攀登者1 C/C源码实现 目录 题目描述&#xff1a; 示例1 代码实现&#xff1a; 题目描述&#xff1a; 攀登者喜欢寻找各种地图&#xff0c;并且尝试攀登到最高的山峰。 地图表示为一维数组&#xff0c;数组的索引代表水平位置&…

C++二分查找算法:有序矩阵中的第 k 个最小数组和

本文涉及的基础知识点 二分查找算法合集 本题的简化 C二分查找算法&#xff1a;查找和最小的 K 对数字 十分接近m恒等于2 题目 给你一个 m * n 的矩阵 mat&#xff0c;以及一个整数 k &#xff0c;矩阵中的每一行都以非递减的顺序排列。 你可以从每一行中选出 1 个元素形成…

哈希unordered_set,unordered_map的练习

349. 两个数组的交集 给定两个数组 nums1 和 nums2 &#xff0c;返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。 示例 1&#xff1a; 输入&#xff1a;nums1 [1,2,2,1], nums2 [2,2] 输出&#xff1a;[2]示例 2&#xff1a; 输…

JSP过滤器和监听器

什么是过滤器 Servlet过滤器与Servlet十分相似&#xff0c;但它具有拦截客户端&#xff08;浏览器&#xff09;请求的功能&#xff0c;Servlet过滤器可以改变请求中的内容&#xff0c;来满足实际开发中的需要。 对于程序开发人员而言&#xff0c;过滤器实质就是在Web应用服务器…

使用Wireshark提取流量中图片方法

0.前言 记得一次CTF当中有一题是给了一个pcapng格式的流量包&#xff0c;flag好像在某个响应中的图片里。比较简单&#xff0c;后来也遇到过类似的情况&#xff0c;所以总结和记录一下使用Wireshark提取图片的方法。 提取的前提是HTTP协议&#xff0c;至于HTTPS的协议需要导入服…

【算法】摩尔投票算法

目录 1.概述2.算法思想3.代码实现3.1.t ⌊n / 2⌋3.2.t ⌊n / 3⌋3.3.t ⌊n / (m 1)⌋ 4.应用 参考&#xff1a;LeetCode_多数元素 II 题解 1.概述 &#xff08;1&#xff09;摩尔投票法 (Boyer–Moore Majority Vote Algorithm) 是一种用来寻找一组元素中多数元素的常量级…

flutter,uni-app开发调试ios

一、申请ios开发者账号 二、ios开发者配置 ios 开发者需要配置的地方 https://developer.apple.com/account/resources/certificates/list Certificates&#xff08;证书&#xff09;: 作用&#xff1a; 证书用于对应用程序和开发者进行身份验证&#xff0c;确保安全性和可…

如何为您的企业选择合适的多因素认证?

在传统的网络安全架构中&#xff0c;重点在于防止非法入侵&#xff0c;例如防火墙、VPN 、堡垒机等安全设备的重心都在于防止用户违规访问企业资源&#xff0c;一旦合法用户的账号密码被入侵者拿到&#xff0c;就可以冒充合法用户访问企业资源&#xff0c;所有的安全设备形同虚…

springcloud超市管理系统源码

技术说明&#xff1a; jdk1.8&#xff0c;mysql5.7&#xff0c;idea&#xff0c;vscode springcloud springboot mybatis vue elementui mysql 功能介绍&#xff1a; 后台管理&#xff1a; 统计分析&#xff1a;查看用户&#xff0c;商品&#xff0c;销售数量&#xff1b;…

Mock 数据

1. Mock 数据的方式 2. json-server 实现 Mock 数据 项目中安装json-server npm i -D json-server准备一个json文件添加启动命令 //package.json"scripts": {"start": "craco start","build": "craco build","test&q…

简单聊聊加密和加签的关系与区别

大家好&#xff0c;我是G探险者。 平时我们在项目上一定都听过加密和加签&#xff0c;加密可能都好理解&#xff0c;知道它是保障的数据的机密性&#xff0c;那加签是为了保障啥勒&#xff1f;它和加密有啥区别&#xff1f; 带着这个疑问&#xff0c;我们就来聊聊二者的区别。…

SHEIN出口车钥匙扣REACH认证指南解析

钥匙扣的材料一般为金属、皮革、塑料、橡胶、木头等。此物精致小巧、造型千变万化是人们随身携带的日常用品。钥匙扣是挂在钥匙圈上的一种装饰物品。钥匙扣出口需要办理REACH认证。 一、什么是REACH认证&#xff1f; REACH认证是欧盟28个成员国对进入其市场的所有化学品,&…

centos7中通过minikube安装Kubernetes

minikube是一款开源的Kubernetes集群管理器&#xff0c;它可以帮助您在本地计算机上轻松部署和管理Kubernetes集群。以下是minikube的安装和使用步骤&#xff1a; 安装Docker&#xff1a;如果您还没有安装Docker&#xff0c;可以从Docker官方网站上下载并安装适合您操作系统的…