【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.pswp.cn/news/164819.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/164819.shtml
英文地址,請注明出處:http://en.pswp.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官方網站上下載并安裝適合您操作系統的…