【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.rhkb.cn/news/202723.html

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

相关文章

HTML新特性【缩放图像、图像切片、平移、旋转、缩放、变形、裁切路径、时钟、运动的小球】(二)-全面详解(学习总结---从入门到深化)

目录 绘制图像_缩放图像 绘制图像_图像切片 Canvas状态的保存和恢复 图形变形_平移 图形变形_旋转 图形变形_缩放 图形变形_变形 裁切路径 动画_时钟 动画_运动的小球 引入外部SVG 绘制图像_缩放图像 ctx.drawImage(img, x, y, width, height) img &#xf…

C# 使用NPOI操作Excel的工具类

写在前面 NPOI是POI项目的.NET迁移版本。POI是一个开源的Java 读写 Excel、Word 等微软Ole2组件文档的项目&#xff1b;使用NPOI可以在没有安装Office或者相应环境的机器上对Word或Excel文档进行读写操作。 NPOI类库中操作EXCEL有两个模块分别是&#xff1a; 1️.HSSF模块&a…

Spring Beans;Spring Bean的生命周期;spring Bean的作用域,spring处理线程并发问题

文章目录 Spring Beans请解释Spring Bean的生命周期解释Spring支持的几种bean的作用域Spring容器中的bean可以分为5个范围&#xff1a; Spring如何处理线程并发问题&#xff1f; 在现在的项目开发中经常使用到spring bean&#xff0c;那么来谈谈spring bean的生命周期&#xff…

Lua脚本解决redis实现的分布式锁多条命令原子性问题

线程1现在持有锁之后&#xff0c;在执行业务逻辑过程中&#xff0c;他正准备删除锁&#xff0c;而且已经走到了条件判断的过程中&#xff0c;比如他已经拿到了当前这把锁确实是属于他自己的&#xff0c;正准备删除锁&#xff0c;但是此时他的锁到期了&#xff0c;那么此时线程2…

(三) Windows 下 Sublime Text 3 配置Python环境和Anaconda代码提示

一&#xff1a;新建一个 Python3.7 编译环境。 1 Tools--Build System--New Build System... 修改前&#xff1a; 修改后&#xff1a; 内容&#xff1a; {"cmd":["C:\\Python\\Python37-32\\python.exe","-u","$file"],"file_r…

复数的几何意义

1、复平面&#xff0c;复数的其它表示法 (1)几何表示法 直角平面坐标&#xff1a; 复平面 实轴&#xff0c;虚轴 (2)向量表示法 向量 模&#xff1a; 复数加减法可用向量的三角形法则或者平行四边形法则 (3)结论 (两边之和大于第三边) ((两边之差大于第三边)) *辐角&am…

FlinkCDC实现主数据与各业务系统数据的一致性(瀚高、TIDB)

文章末尾附有flinkcdc对应瀚高数据库flink-cdc-connector代码下载地址 1、业务需求 目前项目有主数据系统和N个业务系统,为保障“一数一源”,各业务系统表涉及到主数据系统的字段都需用主数据系统表中的字段进行实时覆盖,这里以某个业务系统的一张表举例说明:业务系统表Ta…

pytorch安装GPU版本 (Cuda12.1)教程

使用本教程前&#xff0c;默认您已经安装并配置好了python3以上版本 1. 去官网下载匹配的Cuda Cuda下载地址 当前最高版本的Cuda是12.1 我安装的就是这个版本 小提示&#xff1a;自定义安装可以只选择安装Cuda Runtime。Nvidia全家桶不必全部安装。把全家桶全部安装完直接系统…

机器人规划算法——movebase导航框架源码分析

这里对MoveBase类的类成员进行了声明&#xff0c;以下为比较重要的几个类成员函数。 构造函数 MoveBase::MoveBase | 初始化Action 控制主体 MoveBase::executeCb收到目标&#xff0c;触发全局规划线程&#xff0c;循环执行局部规划 全局规划线程 void MoveBase::planThread |…

【小黑送书—第五期】>>《MATLAB科学计算从入门到精通》

从代码到函数&#xff0c;从算法到实战&#xff0c;从问题到应用&#xff0c;由浅入深掌握科学计算方法&#xff0c;高效解决实际问题。 从代码到函数&#xff0c;掌握多种经典算法 跨越多个领域&#xff0c;精通各类科学计算 多种应用实例&#xff0c;高效解决实际问题 今天给…

【尚跑】2023宝鸡马拉松安全完赛,顺利PB达成

1、赛事背景 千年宝地&#xff0c;一马当先&#xff01;10月15日7时30分&#xff0c;吉利银河2023宝鸡马拉松在宝鸡市行政中心广场鸣枪开跑。 不可忽视的是&#xff0c;这次赛事的卓越之处不仅在于规模和参与人数&#xff0c;还在于其精心的策划和细致入微的组织。为了确保每位…

操作NAND flash W25N01G

文章目录 W25N01G1 描述2 特点3 封装3.3.2 连接线 4 引脚/CSDO/WP/Hold SPI指令标准SPI命令双SPI四元SPI命令写保护 5 地址PA与PC最后一个扇区 OTP寄存器1块保护清除块保护指令* WP-E 寄存器2寄存器3BUSYP-FAILE-FAILECC位 8 命令8.1 装置ID 指令解读写状态寄存器 注意内容上拉…

今天给大家带来Python炫酷爱心代码

前言&#xff1a; 这个是小编之前朋友一直要小编去做的&#xff0c;不过之前技术不够所以一直拖欠今天也完成之前的约定吧&#xff01; 至于他是谁&#xff0c;我就不多说了直接上代码 一.代码展示 import random from math import sin, cos, pi, log from tkinter import …

Navicat 技术指引 | 适用于 GaussDB 的用户权限设置

Navicat Premium&#xff08;16.2.8 Windows版或以上&#xff09; 已支持对 GaussDB 主备版的管理和开发功能。它不仅具备轻松、便捷的可视化数据查看和编辑功能&#xff0c;还提供强大的高阶功能&#xff08;如模型、结构同步、协同合作、数据迁移等&#xff09;&#xff0c;这…

SpringMVC系列-7 @CrossOrigin注解与跨域问题

背景 前段时间帮同事分析了一个跨域问题&#xff0c;正好系统分析和整理一下。 1.跨域 理解同源策略是理解跨域的前提。同源策略定义如下&#xff1a; 在同一来源的页面和脚本之间进行数据交互时&#xff0c;浏览器会默认允许操作&#xff0c;而不会造成跨站脚本攻击&#x…

2023年最新前端面试题汇总大全(含答案超详细,HTML,JS,CSS汇总篇)-- 持续更新

专项练习–持续更新 HTML篇CSS篇JS篇Vue篇TypeScript篇React篇微信小程序篇前端面试题汇总大全二&#xff08;含答案超详细&#xff0c;Vue&#xff0c;TypeScript&#xff0c;React&#xff0c;微信小程序&#xff0c;Webpack 汇总篇&#xff09;-- 持续更新 前端面试题汇总大…

Wireshark的捕获过滤器

Wireshark的过滤器&#xff0c;顾名思义&#xff0c;作用是对数据包进行过滤处理。具体过滤器包括捕获过滤器和显示过滤器。本文对捕获过滤器进行分析。 捕获过滤器&#xff1a;当进行数据包捕获时&#xff0c;只有那些满足给定的包含/排除表达式的数据包会被捕获。 捕获过滤器…

float和double(浮点型数据)在内存中的储存方法

作者&#xff1a;元清加油 主页&#xff1a;主页 编译环境&#xff1a;visual studio 2022 (x86) 相信大家都知道数据在内存中是以二进制储存的 整数的储存方法是首位是符号位&#xff0c;后面便是数值位 那么浮点数在内存中是怎么储存的呢&#xff1f;我们先来看一个例子&am…

深度学习技巧应用30-深度学习中的GPU的基本架构原理与应用技巧

大家好,我是微学AI,今天给大家介绍一下深度学习技巧应用30-深度学习中的GPU的基本架构原理与应用技巧,GPU是一种专门用于处理大量并行操作的硬件设备,它的架构设计主要是为了图形渲染。然而,由于其并行处理能力,现在广泛应用于深度学习、科学计算等领域。主要的GPU制造商…

C#,《小白学程序》第十九课:随机数(Random)第六,随机生成任意长度的大数(BigInteger)

1 文本格式 using System; using System.Linq; using System.Text; using System.Collections.Generic; /// <summary> /// 大数的&#xff08;加减乘除&#xff09;四则运算、阶乘运算 /// 乘法计算包括小学生算法、Karatsuba和Toom-Cook3算法 /// 除法运算为 Truffer…