C++?Date類的具體使用(構(gòu)建,重載等)
寫在前面
我們今天寫一個(gè)Date類作為C++初始類的結(jié)尾,這里涉及到的知識(shí),里面有很多運(yùn)算符的重載,包括權(quán)限的問(wèn)題,我們都已經(jīng)分享過(guò)了,所以大家不用擔(dān)心,這里算是一個(gè)總結(jié)吧.我這里用的的是Linux環(huán)境,主要是鍛煉自己的能力.
成果
我們要完成一個(gè)什么樣的Date類呢,大家可以搜一下時(shí)間計(jì)算器,我們就完成他們的功能,比如說(shuō)加減300天或者看看兩個(gè)日期之間的天數(shù),這就是我們要完成的任務(wù).
準(zhǔn)備工作
這里我們用三個(gè)文件來(lái)寫,分別是Date.h,Date.cpp,test.cpp.我們先把初始工作給做好了,我們先把框架各搭出來(lái),后面要的功能一一補(bǔ)足.
Date.h
#include <iostream> #include <assert.h> using std::cout; using std::endl; class Date { public: Date(int year = 1900, int month = 1, int day = 1); //析構(gòu)函數(shù) ~Date(); // 拷貝構(gòu)造 Date(const Date& d); private: int _year; int _month; int _day; };
Date.cpp
#include "Date.h" Date::Date(int year, int month, int day) { } ~Date() { } Date(const Date& d) { }
test.cpp
#include "Date.h" int main() { return 0; }
構(gòu)造函數(shù)
我們先來(lái)寫一下日期類的構(gòu)造函數(shù),本來(lái)這是沒有多少問(wèn)題的,但是我們知道一個(gè)月的天數(shù)是有限制的,而且還有閏年于平年之分,這就考慮的有點(diǎn)難度了,但是這要符合我們的客觀規(guī)律.我們先來(lái)把思路捋順.
第一點(diǎn) 我們把年月份給對(duì)象,其中肯定都是大于0的整數(shù),這個(gè)是毋庸置疑的,第二步,我們要判斷這一年是平年還是閏年,第三步,要判斷給的月數(shù)的對(duì)應(yīng)的天數(shù)是否合理.
我們分別用方法來(lái)完成自己的要求.
判斷平年 or 閏年
這個(gè)很簡(jiǎn)單,記得去類里面聲明這個(gè)方法.
bool Date::isLeap(int year) { assert(year > 0); return (year % 4 == 0 && year %100 != 0) || year % 400 == 0; }
判斷天數(shù)是否合理
我們都知道每一月分都有固定的天數(shù),而且月份是肯定小于13的,
int Date::isLegitimate(int year,int month) { static int monthDay[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31}; assert(month > 0 && month < 13); assert(day > 0); //判斷閏年 && 而且 月份是 2 月 if(isLeap(year) && month == 2) { return 29; } return monthDay[month]; }
我來(lái)解釋一下我們定義數(shù)組的時(shí)候?yàn)槭裁从玫氖?static ? 我們知道,這是一個(gè)函數(shù),也就是說(shuō)函數(shù)棧幀會(huì)在結(jié)束后銷毀,但是我們可能多次調(diào)用這個(gè)函數(shù),為了避免多次開辟和銷毀該數(shù)組的空間,這里直接用static修飾得了.
寫好構(gòu)造函數(shù)
到這里我們已經(jīng)寫好了的構(gòu)造函數(shù),沒必要在說(shuō)其他了.
Date::Date(int year = 1900, int month = 1, int day = 1) { if(year > 0 && month > 0 && month <13 && day <= isLegitimate(year,month)) { _year = year; _month = month; _day = day; } else { // 這里應(yīng)該拋出一個(gè)異常 // 現(xiàn)在我還不太會(huì) 暫時(shí)用 assert代替 assert(NULL); } }
析構(gòu)函數(shù) & 拷貝構(gòu)造
說(shuō)實(shí)話,這兩個(gè)函數(shù)我們不用寫,主要是我們沒有使用動(dòng)態(tài)開辟空間,都是一些基本的內(nèi)容,編譯器生成的已經(jīng)完全夠了,這里大家看看就行了.
由于這兩個(gè)函數(shù)都不大,這里就聲明成內(nèi)聯(lián)函數(shù)函數(shù)吧,在類內(nèi)實(shí)現(xiàn).
// 析構(gòu)函數(shù) inline ~Date() { _year = 0; _month = 0; _day = 0; } // 拷貝構(gòu)造 inline Date(const Date& d) { _year = d._year; _month = d._month; _day = d._day; }
運(yùn)算符重載
某種意義上,運(yùn)算符重載才是我們今天的大頭,我們不是重載所有的運(yùn)算符,而是要重載那些符合我們邏輯的,例如一個(gè)日期加上一個(gè)日期就沒有什么意義,這里就不會(huì)重載它.
邏輯運(yùn)算符的重載
這個(gè)基本的邏輯運(yùn)算符都有意義,這里我們一一給大家重載出來(lái),同時(shí)也驗(yàn)證一下.
重載 ==
這個(gè)很好寫,如果日期的年月日都相等,那么這兩個(gè)日期一定相等.
bool Date:: operator==(const Date& d) const { return _year == d._year && _month == d._month && _day == d._day; }
重載 >
如果一個(gè)日期的年數(shù)比較大,那么它一定更大,如果相等,就比較月份,如果月份還相等,那就比較天數(shù),這就是這個(gè)的原理.
bool Date:: operator>(const Date& d) const { return (_year > d._year) ||(_year == d._year && _month > d._month) ||(_year == d._year && _month == d._month && _day > d._day); }
重載 >=
只要我們完成了上面的兩個(gè),后面就可以直接調(diào)用它們了,避免重復(fù)造輪子.
bool Date::operator>=(const Date& d) const { return *this > d || *this == d; }
重載 <
從這里開始,我就不演示結(jié)果了,都是和之前的一樣.
我們知道,小于的對(duì)立面就是大于大于等于
bool Date::operator<(const Date& d) const { return !(*this >= d); }
重載 <=
小于等于的對(duì)立面是大于,我們已經(jīng)實(shí)現(xiàn)了.
bool Date::operator<=(const Date& d) const { return !(*this > d); }
重載 !=
這個(gè)更加簡(jiǎn)單,不等于不就是等于的對(duì)立面嗎
bool Date::operator!=(const Date& d) const { return !(*this == d); }
算數(shù)運(yùn)算符的重載
上面的都挺簡(jiǎn)單的,這里算數(shù)運(yùn)算符我們要重載的有加法,等于,減法,前置和后置++…有一定的額難度,尤其是加法和減法.
重載 =
等于的重載基本來(lái)說(shuō)對(duì)于我們是沒有任何問(wèn)題的,但是有一點(diǎn)是需要我們注意的,無(wú)論是C語(yǔ)言還是C++都是支持連等的,也就是a = b = c,那就意味者我們們重載等于的時(shí)候是要有返回值的.
Date& Date::operator=(const Date& d) { // 避免 重復(fù) if(this != &d) { _year = d._year; _month = d._month; _day = d._day; } return *this; }
重載 +
說(shuō)實(shí)話,加號(hào)還是比較簡(jiǎn)單的,我們首先要把給的天數(shù)判斷一下,假如要是小于零,就去調(diào)用重載的減號(hào),后面我會(huì)實(shí)現(xiàn)減法的,這里先考慮好.
那么我們?cè)撊绾伟堰@個(gè)邏輯給完善好呢?第一步,就是把給的天數(shù)直接加到_day上面,如果還沒有超過(guò)當(dāng)前月最大的天數(shù),我們就直接返回這個(gè)日期就可以了,否則就把日期減去當(dāng)前月最大的天數(shù),當(dāng)前月加一,注意,這里要明白,如果當(dāng)前月是12月,我們直接把月份置為1,年加上一,這里要注意一點(diǎn)東西 ,我們不修改原來(lái)的日期
我們可以分為三種情況,每一個(gè)我都列出來(lái),本質(zhì)上是一個(gè)循環(huán).
- 2022-2-1 + 12 _day = 13 < 2月份的最大值,返回 2022-2-13
- 2022-4-30 + 7 _day = 37 > 4月份最大值, _day-=30 月份+1 = 5,我們發(fā)現(xiàn) _day = 7 < 5月份的最大值,循環(huán)結(jié)束
- 2022-12-31 + 2 _day = 33 > 12月份最大值, _day-=31,月份是12,直接置為1, _year加1,繼續(xù)循環(huán),判斷 _day = 2是不是滿足循環(huán)條件
Date Date::operator+(const int day) const { //先判斷 day 是否是 小于零 if(day < 0) { return (*this)-(-day); } // 第一步 來(lái)個(gè)第三方 不要修改原來(lái)的 Date ret(*this); // 這是拷貝構(gòu)造 ret._day += day; while(ret._day > ret.isLegitimate(ret._year,ret._month)) { ret._day -= ret.isLegitimate(ret._year,ret._month); if(ret._month == 12) { ret._month = 1; ret._year += 1; } else { ret._month += 1; } } return ret; }
重載+=
我們直接復(fù)用+和=就可以了,這里沒什么可以分享的.
Date& Date::operator+=(const int day) { //判斷 是不是 小于 0 if(day < 0) { return (*this) = (*this) - (-day); } return (*this) = (*this) + day; }
重載 -
我們們這里要重載加號(hào)的的話,需要分為兩種共請(qǐng)情況
- 參數(shù) 是 天數(shù)
- 參數(shù) 是 日期
很榮幸,C++是支持重載的,我們也按照步驟來(lái).
參數(shù)是天數(shù)
這個(gè)就是計(jì)算一個(gè)日期減去多少天得到另一個(gè)日期,也是比較簡(jiǎn)單的,我們要考慮一些之情況,這里小于零的情況就不解釋了,主要看我們的思路是什么.
我們首先把_day減去day,判斷是不是小于0,小于的話,就從上個(gè)月的日期天數(shù)加到 _day上,直到它它大于0,這里要注意的是,如果我們的月份恰好是12,那么上一個(gè)月是1月份,并且年也要減1
Date Date::operator-(const int day) const { // day 的大小 if(day < 0) { return (*this) + (-day); } Date ret(*this); ret._day -= day; //開始判斷 ret._day while(ret._day <= 0) { // 找上一個(gè)月的 if(ret._month == 1) { ret._month = 12; ret._year -= 1; } else { ret._month -= 1; } int days = ret.isLegitimate(ret._year,ret._month); ret._day += days; } return ret; }
參數(shù)是日期
這個(gè)更加簡(jiǎn)單的,我們計(jì)算的是兩個(gè)日期之間差的天數(shù),我們可以復(fù)用前面的方法.
還是先說(shuō)下思路,我們想,如果一個(gè)較小的日期每次加一,直到加到和較大的日期完全一樣,我們計(jì)算加的次數(shù)是不是就可以完成這個(gè)操作符的重載了.那么我們?nèi)绾我玫礁〉娜掌?是不是要比較,然后交換這里是不用的,我們用一個(gè)標(biāo)志位.我們假設(shè)日期A比日期B小,標(biāo)志位flag = 1,如果不成立,我們把flag編程-1,隨即我們用日期A加上flag,進(jìn)行循環(huán).
int Date:: operator-(const Date& d) { // 給一個(gè) 數(shù) 來(lái)計(jì)數(shù) int count = 0; int flag = 1; // 不能修改原來(lái)的,這里用一個(gè)第三方 Date ret(*this); if(ret > d) { flag = -1; } while(ret != d) { ret += flag; count++; } return flag*count; }
重載-=
這個(gè)我們復(fù)用減號(hào)就可以了,就不解釋了.
Date& Date::operator-=(const int day) { if(day < 0) { return(*this) = (*this)+(-day); } return (*this) = (*this) - day; }
重載++
我們這就不解釋前置和后置的區(qū)別了,上一個(gè)博客分享過(guò)了,直接開始吧.
前置
前置是不需要帶參數(shù)的.
Date& Date::operator++() { *this += 1; return *this; }
后置
需要帶一個(gè)int類型的參數(shù)
Date Date::operator++(int day) { Date ret(*this); *this += 1; return ret; }
重載 –
既然我們都把減法給重載了,那這我們直接復(fù)用就可以了
前置
不帶參數(shù)
Date& Date::operator--() { *this -= 1; return *this; }
后置
帶上參數(shù)
Date Date:: operator--(int day) { Date ret(*this); *this -= 1; return ret; }
重載流提取 & 流插入
這原理我們已經(jīng)分享過(guò)了,這里就不加贅述了,記得使用友元
>>
std::istream& operator>>(std::istream& in, Date& d) { in >> d._year >> d._month >> d._day; return in; }
<<
std::ostream& operator<<(std::ostream& out, Date& d) { out << d._year << "-" << d._month << "-" << d._day; return out; }
到此這篇關(guān)于C++ Date類的具體使用(構(gòu)建,重載等)的文章就介紹到這了,更多相關(guān)C++ Date類內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Qt 鼠標(biāo)/觸屏繪制平滑曲線(支持矢量/非矢量方式)
這篇文章主要介紹了Qt 鼠標(biāo)/觸屏繪制平滑曲線(支持矢量/非矢量方式),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04C語(yǔ)言?超詳細(xì)總結(jié)講解二叉樹的概念與使用
二叉樹可以簡(jiǎn)單理解為對(duì)于一個(gè)節(jié)點(diǎn)來(lái)說(shuō),最多擁有一個(gè)上級(jí)節(jié)點(diǎn),同時(shí)最多具備左右兩個(gè)下級(jí)節(jié)點(diǎn)的數(shù)據(jù)結(jié)構(gòu)。本文將詳細(xì)介紹一下C++中二叉樹的概念和結(jié)構(gòu),需要的可以參考一下2022-04-04C++多重繼承引發(fā)的重復(fù)調(diào)用問(wèn)題與解決方法
這篇文章主要介紹了C++多重繼承引發(fā)的重復(fù)調(diào)用問(wèn)題與解決方法,結(jié)合具體實(shí)例形式分析了C++多重調(diào)用中的重復(fù)調(diào)用問(wèn)題及相應(yīng)的解決方法,需要的朋友可以參考下2018-05-05如何通過(guò)C++求出鏈表中環(huán)的入口結(jié)點(diǎn)
本文主要介紹了通過(guò)C++求解鏈表中環(huán)的入口結(jié)點(diǎn),即給一個(gè)長(zhǎng)度為n鏈表,若其中包含環(huán),請(qǐng)找出該鏈表的環(huán)的入口結(jié)點(diǎn),否則,返回null。需要的朋友可以參考一下2021-12-12