C++?Date類的具體使用(構(gòu)建,重載等)
寫在前面
我們今天寫一個Date類作為C++初始類的結(jié)尾,這里涉及到的知識,里面有很多運(yùn)算符的重載,包括權(quán)限的問題,我們都已經(jīng)分享過了,所以大家不用擔(dān)心,這里算是一個總結(jié)吧.我這里用的的是Linux環(huán)境,主要是鍛煉自己的能力.
成果
我們要完成一個什么樣的Date類呢,大家可以搜一下時間計(jì)算器,我們就完成他們的功能,比如說加減300天或者看看兩個日期之間的天數(shù),這就是我們要完成的任務(wù).

準(zhǔn)備工作
這里我們用三個文件來寫,分別是Date.h,Date.cpp,test.cpp.我們先把初始工作給做好了,我們先把框架各搭出來,后面要的功能一一補(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ù)
我們先來寫一下日期類的構(gòu)造函數(shù),本來這是沒有多少問題的,但是我們知道一個月的天數(shù)是有限制的,而且還有閏年于平年之分,這就考慮的有點(diǎn)難度了,但是這要符合我們的客觀規(guī)律.我們先來把思路捋順.
第一點(diǎn) 我們把年月份給對象,其中肯定都是大于0的整數(shù),這個是毋庸置疑的,第二步,我們要判斷這一年是平年還是閏年,第三步,要判斷給的月數(shù)的對應(yīng)的天數(shù)是否合理.
我們分別用方法來完成自己的要求.
判斷平年 or 閏年
這個很簡單,記得去類里面聲明這個方法.
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];
}
我來解釋一下我們定義數(shù)組的時候?yàn)槭裁从玫氖?static ? 我們知道,這是一個函數(shù),也就是說函數(shù)棧幀會在結(jié)束后銷毀,但是我們可能多次調(diào)用這個函數(shù),為了避免多次開辟和銷毀該數(shù)組的空間,這里直接用static修飾得了.
寫好構(gòu)造函數(shù)
到這里我們已經(jīng)寫好了的構(gòu)造函數(shù),沒必要在說其他了.
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)該拋出一個異常
// 現(xiàn)在我還不太會 暫時用 assert代替
assert(NULL);
}
}
析構(gòu)函數(shù) & 拷貝構(gòu)造
說實(shí)話,這兩個函數(shù)我們不用寫,主要是我們沒有使用動態(tài)開辟空間,都是一些基本的內(nèi)容,編譯器生成的已經(jīng)完全夠了,這里大家看看就行了.
由于這兩個函數(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)算符,而是要重載那些符合我們邏輯的,例如一個日期加上一個日期就沒有什么意義,這里就不會重載它.
邏輯運(yùn)算符的重載
這個基本的邏輯運(yùn)算符都有意義,這里我們一一給大家重載出來,同時也驗(yàn)證一下.
重載 ==
這個很好寫,如果日期的年月日都相等,那么這兩個日期一定相等.
bool Date:: operator==(const Date& d) const
{
return _year == d._year
&& _month == d._month
&& _day == d._day;
}

重載 >
如果一個日期的年數(shù)比較大,那么它一定更大,如果相等,就比較月份,如果月份還相等,那就比較天數(shù),這就是這個的原理.
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);
}

重載 >=
只要我們完成了上面的兩個,后面就可以直接調(diào)用它們了,避免重復(fù)造輪子.
bool Date::operator>=(const Date& d) const
{
return *this > d || *this == d;
}

重載 <
從這里開始,我就不演示結(jié)果了,都是和之前的一樣.
我們知道,小于的對立面就是大于大于等于
bool Date::operator<(const Date& d) const
{
return !(*this >= d);
}
重載 <=
小于等于的對立面是大于,我們已經(jīng)實(shí)現(xiàn)了.
bool Date::operator<=(const Date& d) const
{
return !(*this > d);
}
重載 !=
這個更加簡單,不等于不就是等于的對立面嗎
bool Date::operator!=(const Date& d) const
{
return !(*this == d);
}
算數(shù)運(yùn)算符的重載
上面的都挺簡單的,這里算數(shù)運(yùn)算符我們要重載的有加法,等于,減法,前置和后置++…有一定的額難度,尤其是加法和減法.
重載 =
等于的重載基本來說對于我們是沒有任何問題的,但是有一點(diǎn)是需要我們注意的,無論是C語言還是C++都是支持連等的,也就是a = b = c,那就意味者我們們重載等于的時候是要有返回值的.
Date& Date::operator=(const Date& d)
{
// 避免 重復(fù)
if(this != &d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
return *this;
}
重載 +
說實(shí)話,加號還是比較簡單的,我們首先要把給的天數(shù)判斷一下,假如要是小于零,就去調(diào)用重載的減號,后面我會實(shí)現(xiàn)減法的,這里先考慮好.
那么我們該如何把這個邏輯給完善好呢?第一步,就是把給的天數(shù)直接加到_day上面,如果還沒有超過當(dāng)前月最大的天數(shù),我們就直接返回這個日期就可以了,否則就把日期減去當(dāng)前月最大的天數(shù),當(dāng)前月加一,注意,這里要明白,如果當(dāng)前月是12月,我們直接把月份置為1,年加上一,這里要注意一點(diǎn)東西 ,我們不修改原來的日期
我們可以分為三種情況,每一個我都列出來,本質(zhì)上是一個循環(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);
}
// 第一步 來個第三方 不要修改原來的
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;
}
重載 -
我們們這里要重載加號的的話,需要分為兩種共請情況
- 參數(shù) 是 天數(shù)
- 參數(shù) 是 日期
很榮幸,C++是支持重載的,我們也按照步驟來.
參數(shù)是天數(shù)
這個就是計(jì)算一個日期減去多少天得到另一個日期,也是比較簡單的,我們要考慮一些之情況,這里小于零的情況就不解釋了,主要看我們的思路是什么.
我們首先把_day減去day,判斷是不是小于0,小于的話,就從上個月的日期天數(shù)加到 _day上,直到它它大于0,這里要注意的是,如果我們的月份恰好是12,那么上一個月是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)
{
// 找上一個月的
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ù)是日期
這個更加簡單的,我們計(jì)算的是兩個日期之間差的天數(shù),我們可以復(fù)用前面的方法.
還是先說下思路,我們想,如果一個較小的日期每次加一,直到加到和較大的日期完全一樣,我們計(jì)算加的次數(shù)是不是就可以完成這個操作符的重載了.那么我們?nèi)绾我玫礁〉娜掌?是不是要比較,然后交換這里是不用的,我們用一個標(biāo)志位.我們假設(shè)日期A比日期B小,標(biāo)志位flag = 1,如果不成立,我們把flag編程-1,隨即我們用日期A加上flag,進(jìn)行循環(huán).
int Date:: operator-(const Date& d)
{
// 給一個 數(shù) 來計(jì)數(shù)
int count = 0;
int flag = 1;
// 不能修改原來的,這里用一個第三方
Date ret(*this);
if(ret > d)
{
flag = -1;
}
while(ret != d)
{
ret += flag;
count++;
}
return flag*count;
}
重載-=
這個我們復(fù)用減號就可以了,就不解釋了.
Date& Date::operator-=(const int day)
{
if(day < 0)
{
return(*this) = (*this)+(-day);
}
return (*this) = (*this) - day;
}
重載++
我們這就不解釋前置和后置的區(qū)別了,上一個博客分享過了,直接開始吧.
前置
前置是不需要帶參數(shù)的.
Date& Date::operator++()
{
*this += 1;
return *this;
}
后置
需要帶一個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)分享過了,這里就不加贅述了,記得使用友元
>>
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)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解Dijkstra算法原理及其C++實(shí)現(xiàn)
Dijkstra算法用于計(jì)算一個節(jié)點(diǎn)到其他節(jié)點(diǎn)的最短路徑。Dijkstra是一種按路徑長度遞增的順序逐步產(chǎn)生最短路徑的方法,是一種貪婪算法。本文將詳解Dijkstra算法原理及其C++實(shí)現(xiàn),感興趣的可以了解一下2022-07-07
深入解析C++中的函數(shù)模板和函數(shù)的默認(rèn)參數(shù)
這篇文章主要介紹了深入解析C++中的函數(shù)模板和函數(shù)的默認(rèn)參數(shù),是C++入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下2015-09-09
C語言中獲取進(jìn)程識別碼的相關(guān)函數(shù)
這篇文章主要介紹了C語言中獲取進(jìn)程識別碼的相關(guān)函數(shù),分別為getpid()函數(shù)和getppid()函數(shù)的使用,需要的朋友可以參考下2015-08-08

