中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

中國(guó)住房和城鄉(xiāng)建設(shè)部建造師網(wǎng)站百度推廣云南總代理

中國(guó)住房和城鄉(xiāng)建設(shè)部建造師網(wǎng)站,百度推廣云南總代理,wordpress系統(tǒng)在線升級(jí),科技公司宣傳冊(cè)設(shè)計(jì)樣本文章目錄前言1. 日期的合法性判斷2. 日期天數(shù)&#xff08;/&#xff09;2.1 和的重載2.2 對(duì)于兩者復(fù)用的討論3. 前置和后置重載4. 日期-天數(shù)&#xff08;-/-&#xff09;5. 前置- -和后置- -的重載6. 日期-日期7. 流插入<<重載8. 流提取>>重載9. 總結(jié)10. 源碼展示前…

文章目錄

    • 前言
    • 1. 日期的合法性判斷
    • 2. 日期+天數(shù)(+/+=)
      • 2.1 +和+=的重載
      • 2.2 對(duì)于兩者復(fù)用的討論
    • 3. 前置++和后置++重載
    • 4. 日期-天數(shù)(-/-=)
    • 5. 前置- -和后置- -的重載
    • 6. 日期-日期
    • 7. 流插入<<重載
    • 8. 流提取>>重載
    • 9. 總結(jié)
    • 10. 源碼展示

前言

在上一篇文章我們學(xué)習(xí)類和對(duì)象的過(guò)程中,我們不是寫了一個(gè)日期類嘛。
但是我們之前實(shí)現(xiàn)的日期類并不是很完整,我們只是借助它來(lái)幫大家學(xué)習(xí)類和對(duì)象的知識(shí)。
那這篇文章呢,我們就在之前的基礎(chǔ)上,再增添一些功能,實(shí)現(xiàn)一個(gè)比較完整的日期類,作為一個(gè)練習(xí),來(lái)幫助我們更好的理解我們之前學(xué)過(guò)的知識(shí)。

這是我們之前一起寫的不太完整的日期類:

class Date
{
public://構(gòu)造函數(shù)Date(int year = 1, int month = 1, int day = 1){_year = year;_month = month;_day = day;}//拷貝構(gòu)造函數(shù)Date(const Date& d){_year = d._year;_month = d._month;_day = d._day;}bool operator<(const Date& d){if (_year < d._year)return true;else if (_year == d._year && _month < d._month)return true;else if (_year == d._year && _month == d._month && _day < d._day)return true;return false;}bool operator<=(const Date& d){return *this == d || *this < d;}bool operator>(const Date& d){return !(*this <= d);}bool operator>=(const Date& d){return !(*this < d);}bool operator!=(const Date& d){return !(*this == d);}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}bool operator==(const Date& d){return _year == d._year&& _month == d._month&& _day == d._day;}//賦值重載(對(duì)于Date類用默認(rèn)生成的就行)//d1=d2(this就是d1,d就是d2)/*Date& operator=(const Date& d){if (this != &d){_year = d._year;_month = d._month;_day = d._day;}return *this;}*/
private:int _year;int _month;int _day;
};

那這些實(shí)現(xiàn)過(guò)的函數(shù)我們就不再一一講解了,大家不熟悉的話可以回顧一下上一篇文章。
另外呢,我們最終實(shí)現(xiàn)的是一個(gè)完整的日期類,那方便對(duì)代碼進(jìn)行維護(hù)和管理,以及對(duì)實(shí)現(xiàn)好的日期類進(jìn)行測(cè)試,我們還是像之前寫數(shù)據(jù)結(jié)構(gòu)一樣,放在多個(gè)文件中。

1. 日期的合法性判斷

我們之前呢已經(jīng)給該日期類寫好了構(gòu)造函數(shù):

Date(int year = 1, int month = 1, int day = 1)
{_year = year;_month = month;_day = day;
}

并且還指定了缺省參數(shù),那這樣的話在實(shí)例化一個(gè)對(duì)象時(shí)我們就可以自己給對(duì)象指定初值,我們輸入的日期是啥,該對(duì)象就會(huì)被初始化為對(duì)應(yīng)的日期。

那現(xiàn)在有一個(gè)問(wèn)題,如果我們實(shí)例化對(duì)象時(shí)給的日期不合法呢?比如:

void Datetest1()
{Date d1(2023, 2, 30);d1.Print();
}

在這里插入圖片描述

不合法是不是也判斷不出來(lái)啊。
那我們就對(duì)原來(lái)的構(gòu)造函數(shù)做一些補(bǔ)充好吧,讓它在給對(duì)象初始化的時(shí)候可以去判斷一下對(duì)應(yīng)的日期合不合法。

那要怎么判斷呢?

給我們一個(gè)年月日,要判斷是否合法,是不是要判斷月在不在【1,12】之內(nèi)以及天數(shù)有沒(méi)有超過(guò)當(dāng)前月的總天數(shù)啊。
但是某個(gè)月的天數(shù)是不是不好確定啊,不同月的天數(shù)不一樣,而且要考慮平閏年。

那我們先來(lái)寫一個(gè)獲取某年某月天數(shù)的函數(shù):

int Date::GetMonthDay(int year, int month)
{assert(month > 0 && month < 13);int MonthArr[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;}else{return MonthArr[month];}
}

不過(guò)多解釋了,相信大家都能看懂。

那有了這個(gè)函數(shù),我們就可以在構(gòu)造函數(shù)中去判斷了:

Date::Date(int year, int month, int day)
{if (month > 0 && month < 13 && day>0 && day <= GetMonthDay(year, month)){_year = year;_month = month;_day = day;}else{cout << "日期非法" << endl;_year = 1;_month = 1;_day = 1;}
}

如果合法了,我們?cè)偃ベx值,不合法就還全搞成1,要不然就是隨機(jī)值了。

那這時(shí)我們?cè)儆梅欠ㄈ掌谌コ跏蓟瘜?duì)象:
在這里插入圖片描述

這樣輸入的日期不合法就提示了。

2. 日期+天數(shù)(+/+=)

我們說(shuō)日期+日期是不是沒(méi)啥意義啊,但是日期+一個(gè)天數(shù)是不是還有點(diǎn)意義,可以理解成這么多天之后是幾幾年幾月幾日。

2.1 +和+=的重載

所以接下來(lái),我們要實(shí)現(xiàn)一個(gè)功能就是計(jì)算一個(gè)日期加了一個(gè)天數(shù)之后得到的日期:

那具體實(shí)現(xiàn)的思路呢可以這樣搞:
首先我們想讓自定義類型Date的對(duì)象直接和整型相加,這里肯定要對(duì)+進(jìn)行運(yùn)算符重載。
我們拿到一個(gè)日期一個(gè)天數(shù)之后,先把天數(shù)加到日上,然后,判斷此時(shí)的日是否超過(guò)了當(dāng)前月的總天數(shù)(獲取月份天數(shù)的函數(shù)我們之前已經(jīng)實(shí)現(xiàn)過(guò)了),超過(guò)的話,就減去當(dāng)前月的天數(shù),然后月份++,那月份++有可能會(huì)超過(guò)12啊,一旦超過(guò),就讓年++,然后月置成1。
那當(dāng)然這肯定是一個(gè)循環(huán),當(dāng)我們的日(day)不再大于當(dāng)前月的天數(shù),則此時(shí)得到的就是最終的日期。

我們來(lái)寫一下代碼:

Date& Date::operator+(int day)
{_day += day;while (_day > GetMonthDay(_year, _month)){_day -= GetMonthDay(_year, _month);_month++;if (_month == 13){_year++;_month = 1;}}return *this;
}

這里*this出了作用域還在,所以可以返回引用。

那我們來(lái)測(cè)試一下:

在這里插入圖片描述
在這里插入圖片描述
我們看這個(gè)計(jì)算出來(lái)的日期確實(shí)是沒(méi)問(wèn)題的,但是d1+100,這里是+而不是+=,所以d1是不是不應(yīng)該變啊,我們只是把d1+100得到的日期賦給了d2,但是現(xiàn)在d1也變了。
所以我們這樣寫其實(shí)實(shí)現(xiàn)的是啥,是不是+=啊。

所以我們這里重載的應(yīng)該是+=:

Date& Date::operator+=(int day)
{_day += day;while (_day > GetMonthDay(_year, _month)){_day -= GetMonthDay(_year, _month);_month++;if (_month == 13){_year++;_month = 1;}}return *this;
}

那+=還需要有返回值嗎,🆗,最好還是帶返回值,帶返回值的話就可以支持這種情況:d2 = d1 += 100;

那剛才實(shí)現(xiàn)的是+=,那+要這么搞?

是不是借助一個(gè)臨時(shí)對(duì)象就可以搞定了啊,我們只要不改變*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;
}

那就這樣,測(cè)試一下:
在這里插入圖片描述

🆗,這次d1沒(méi)有被改變。
在這里插入圖片描述
答案也沒(méi)問(wèn)題。

那對(duì)于+的重載:

大家有沒(méi)有注意到我們沒(méi)有返回引用,為什么?
因?yàn)槲覀兎祷氐氖巧?#xff0c;是不是tmp,而tmp是一個(gè)局部的對(duì)象,出了作用域就銷毀了,所以我們不能返回引用。
那有時(shí)候呢,有的人為了這個(gè)地方能夠返回引用,對(duì)tmp加了一個(gè)static修飾,然后就返回引用。
在這里插入圖片描述

大家思考一下這樣可以嗎?

我們?cè)囈幌聲?huì)發(fā)現(xiàn):
在這里插入圖片描述
第一次沒(méi)問(wèn)題,但我們第二次在調(diào)用+,是不是就錯(cuò)了啊。
在這里插入圖片描述
第二次我們還是給d1+1000天,但結(jié)果卻是2000天之后的。

為什么會(huì)這樣?

原因就在于我們用了static。
我們創(chuàng)建的局部對(duì)象tmp被static修飾后,就不存在棧區(qū)了,而是放在靜態(tài)區(qū)了,所以靜態(tài)局部變量出作用域不會(huì)被銷毀,而是保留在靜態(tài)區(qū),因此我們確實(shí)可以返回引用了。
但是,靜態(tài)局部變量的初值是在編譯期間就指定的,所以運(yùn)行期間,不管我們?cè)偃フ{(diào)用幾次函數(shù),tmp都不會(huì)被重新初始化,而是保留上次的值,所以我們第二次的結(jié)果才會(huì)變成2000天之后。

之前有篇文章詳解static的作用,大家可以看——鏈接: link
所以呢,這個(gè)地方我們不要為了能夠返回引用而去隨便加static。

2.2 對(duì)于兩者復(fù)用的討論

那除此之外:

大家看,+的重載與+=的重載,除了多一個(gè)臨時(shí)的局部對(duì)象,其它的邏輯是不是一樣啊,所以+里面是不是可以復(fù)用+=啊。

Date Date::operator+(int day)
{Date tmp(*this);tmp += day;return tmp;
}

這樣是不是就行了啊:
在這里插入圖片描述

那既然+可以復(fù)用+=,我們是不是也可以考慮先實(shí)現(xiàn)+,然后+=復(fù)用+呢?

當(dāng)然可以。

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;
}

那這是我們自己寫的+,現(xiàn)在我們+=來(lái)復(fù)用+。

Date& Date::operator+=(int day)
{*this = *this + day;return *this;
}

這樣不就行了。

那再來(lái)思考:

到底是+復(fù)用+=好呢,還是+=復(fù)用+好呢?
🆗,那這里呢,其實(shí)是我們的第一種即+復(fù)用+=更好一點(diǎn)。
因?yàn)?#43;里面創(chuàng)建臨時(shí)對(duì)象有一次拷貝,返回的是值而不是引用又是一次拷貝。
那如果是+復(fù)用+=的話就只有+里有拷貝,但如果是+=復(fù)用+的話,是不是+=和+里都有拷貝了。

3. 前置++和后置++重載

剛重載了+和+=,那是不是還有前置++和后置++啊,那我們也來(lái)實(shí)現(xiàn)一下。

先來(lái)前置++吧:

來(lái)回憶一下前置++的特性是什么?
是不是先++,后使用啊,即返回的是++之后的值。

舉個(gè)例子:

int a=5;
int b=++a;

首先不管前置++,還是后置++,a的值肯定都會(huì)+1,那現(xiàn)在++a前置,先++后使用,返回++之后的值,所以b也是6。

那我們來(lái)重載一下:

//前置++
Date& Date::operator++()
{*this += 1;return *this;
}

很簡(jiǎn)單,直接復(fù)用+=。

那我們?cè)賮?lái)重載后置++:

后置++呢,是先使用,后++,即返回++之前的值。那我們還是可以借助一個(gè)臨時(shí)對(duì)象。
但是呢?
這里會(huì)發(fā)現(xiàn)有一個(gè)問(wèn)題:
在這里插入圖片描述
前置++和后置++沒(méi)法區(qū)分啊,它們的參數(shù)和函數(shù)名是不是一樣啊。

欸,那這怎么解決啊?

🆗,那當(dāng)然是有辦法的。
前置++和后置++都是一元運(yùn)算符,為了讓前置++與后置++形成能正確重載。C++規(guī)定:后置++重載時(shí)多增加一個(gè)int類型的參數(shù),但調(diào)用函數(shù)時(shí)該參數(shù)不用傳遞(它的作用就是為了構(gòu)成重載),編譯器自動(dòng)傳遞。
在這里插入圖片描述
所以呢,這樣搞就行了。

我們來(lái)實(shí)現(xiàn)一下:

//后置++
Date Date::operator++(int)
{Date tmp(*this);*this += 1;return tmp;
}

🆗,我們就搞定了。

那實(shí)現(xiàn)完了,大家看一下:

前置++和后置++那個(gè)效率會(huì)高一點(diǎn)。
是不是前置啊,因?yàn)榕c后置相比,前置沒(méi)有拷貝啊對(duì)不對(duì)。
所以,對(duì)于內(nèi)置類型來(lái)說(shuō),大家可以認(rèn)為前置后置沒(méi)有區(qū)別;但是對(duì)于自定義類型來(lái)說(shuō),能用前置,盡量用前置++。

我們的前置++和后置++就搞定了,那在調(diào)用的地方呢,我們正常去用就行了,編譯器會(huì)自動(dòng)識(shí)別匹配。
遇到前置++,它就會(huì)自動(dòng)去調(diào)用前置++;遇到后置++,編譯器會(huì)自動(dòng)傳一個(gè)整型參數(shù),去調(diào)用后置++。

4. 日期-天數(shù)(-/-=)

上面我們通過(guò)重載+進(jìn)而實(shí)現(xiàn)計(jì)算一個(gè)日期+一個(gè)天數(shù)之后是什么日期,那是不是還可以搞一下日期-天數(shù),計(jì)算它的前多少天是什么日期。

那我們先來(lái)重載-=:

那思路和上面加一個(gè)天數(shù)也是類似的,我們先用日減去傳過(guò)來(lái)的天數(shù),如果減完之后<=0,說(shuō)明當(dāng)前日期是不合法的,那怎么辦,就去加上一個(gè)月的天數(shù),然后月–,當(dāng)然要注意判斷會(huì)不會(huì)減到上一年,然后還<=0的話,就繼續(xù),知道日>0循環(huán)結(jié)束。

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

測(cè)試一下:
在這里插入圖片描述
在這里插入圖片描述

沒(méi)問(wèn)題。

然后我們?cè)僦剌d一下-:

那是不是簡(jiǎn)單啊,直接復(fù)用-=。

Date Date::operator-(int day)
{Date tmp(*this);tmp -= day;return tmp;
}

測(cè)試 一下:
在這里插入圖片描述

🆗,看起來(lái)好像沒(méi)什么問(wèn)題了,但是,如果這樣呢:
在這里插入圖片描述

這里減一個(gè)負(fù)數(shù),會(huì)發(fā)現(xiàn)結(jié)果就錯(cuò)了。
為什么呢,大家可以調(diào)試觀察:
在這里插入圖片描述
會(huì)發(fā)現(xiàn)這里根本不會(huì)進(jìn)入循環(huán),直接就返回了。

所以針對(duì)負(fù)數(shù)的情況,我們要單獨(dú)處理一下:

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

我們-是復(fù)用-=的,所以這里在-=里面處理。
-=一個(gè)-100就相當(dāng)于+=一個(gè)100嘛。
在這里插入圖片描述

那同樣對(duì)于+和+=我們也要處理一下:

在這里插入圖片描述
在這里插入圖片描述

那我們來(lái)處理一下:

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

這樣是不是就行了,+=一個(gè)-100就相當(dāng)于-=一個(gè)100嘛。
在這里插入圖片描述

5. 前置- -和后置- -的重載

那有了上面的練習(xí),再實(shí)現(xiàn)前置- -和后置- -不是soeasy嘛。

前置- -:

Date& Date::operator--()
{*this -= 1;return *this;
}

先- -,后使用,返回- -之后的值。
在這里插入圖片描述

后置- -:

Date Date::operator--(int)
{Date tmp(*this);*this -= 1;return tmp;
}

先使用,后- -,返回- -之前的值。
在這里插入圖片描述

6. 日期-日期

上面我們搞了日期加減天數(shù),那兩個(gè)日期相減是不是也有意義啊,可以得出這兩個(gè)日期之間差了多少天。

那如何計(jì)算兩個(gè)日期之間相差的天數(shù)呢?

🆗,那這里給大家提供一種比較好實(shí)現(xiàn)的思路:
我們拿到兩個(gè)日期之后,先把較小的那個(gè)日期找出來(lái),然后用一個(gè)計(jì)數(shù)器,統(tǒng)計(jì)較小日期++的次數(shù),當(dāng)兩個(gè)日期相等時(shí)停止,++的次數(shù)就是相差的天數(shù)。
另外如果是第一個(gè)日期大于第二個(gè),結(jié)果應(yīng)該是整數(shù);如果第二個(gè)大于第一個(gè),應(yīng)該是負(fù)數(shù)。

我們來(lái)實(shí)現(xiàn)一下:

//日期-日期
int Date::operator-(Date d)
{Date max = *this;Date min = d;int flag = 1;if (*this < d){max = d;min = *this;flag = -1;}int n = 0;while (min != max){++min;++n;}return n * flag;
}

在這里插入圖片描述
在這里插入圖片描述

沒(méi)有問(wèn)題。

7. 流插入<<重載

那我們現(xiàn)在打印一個(gè)日期類對(duì)象的時(shí)候是不是都是去調(diào)用我們寫的Print函數(shù)啊,那我們能不能想個(gè)辦法打印日期類也能直接像這樣打印:
在這里插入圖片描述
使用我們之前學(xué)的cout+<<去打印。

大家記不記得:

我們之前文章里學(xué)習(xí)C++輸入輸出的時(shí)候,其實(shí)只是淺淺的提了一下如何去用,并沒(méi)有對(duì)cout、<<和>>進(jìn)行過(guò)多講解。
因?yàn)橐晕覀兡菚r(shí)的知識(shí)儲(chǔ)備還不能很好的理解:

在這里插入圖片描述

那我們現(xiàn)在就可以再嘗試多理解一點(diǎn)東西:

我們發(fā)現(xiàn)我們的自定義類型想用這些運(yùn)算符是不是都要重載啊,除了賦值運(yùn)算符以及取地址運(yùn)算符,因?yàn)橘x值重載和取地址重載是類的6個(gè)默認(rèn)成員函數(shù)之中的,我們不寫編譯器會(huì)自動(dòng)生成一個(gè)。但是在有些情況下根據(jù)實(shí)際情況我們還是需要自己寫。
🆗,這是我們上一篇學(xué)習(xí)的知識(shí),不用過(guò)多說(shuō)明了。

然后呢我們還說(shuō)C++里這樣輸入輸出可以自動(dòng)識(shí)別類型。

那為啥可以自動(dòng)識(shí)別類型,其實(shí)是因?yàn)樗@里對(duì)<<進(jìn)行了函數(shù)重載。
在這里插入圖片描述
為什么我們的內(nèi)置類型可以直接用,因?yàn)閹?kù)里面已經(jīng)對(duì)這些類型都進(jìn)行了重載,所以可以自動(dòng)識(shí)別類型,是根據(jù)操作數(shù)的不同類型進(jìn)行匹配。

那我們現(xiàn)在自定義類型想用怎么辦,是不是需要自己重載啊。

那我們接下來(lái)就重載一下<<好吧:

void operator<<(ostream& out);

那想用<<是不是得使用cout<<兩個(gè)操作數(shù),一個(gè)cout,一個(gè)是我們要打印得對(duì)象,cout是啥?
🆗,上面說(shuō)了它是一個(gè)ostream 類型得對(duì)象,所以我們把cout作為參數(shù)傳過(guò)去。
那這里out就用來(lái)接收cout,this指針指向得就是我們要打印得類對(duì)象。

來(lái)實(shí)現(xiàn)一下:

void Date::operator<<(ostream& out)
{out << _year << _month << _day << endl;
}

這樣是不是就行了啊,它的成員變量都是內(nèi)置類型,我們就可以使用<<直接打印了。

我們測(cè)試一下:
在這里插入圖片描述

但是我們使用的時(shí)候發(fā)現(xiàn)報(bào)錯(cuò)了。

這里操作數(shù)是不是寫反了,為什么?

對(duì)于函數(shù)重載來(lái)說(shuō),兩個(gè)參數(shù)的話,第一個(gè)參數(shù)是左操作數(shù),第二個(gè)參數(shù)是右操作數(shù)。
但是對(duì)于類成員函數(shù)來(lái)說(shuō),第一個(gè)參數(shù)是不是隱藏的this指針啊,它指向我們調(diào)用該函數(shù)的對(duì)象,所以這里第一個(gè)參數(shù)是Date對(duì)象的地址。

那我們要調(diào)用的話,應(yīng)該這樣寫:
在這里插入圖片描述

但是這樣寫是不是好別扭啊。

怎么讓它像內(nèi)置類型那樣使用啊。

那我們就要想辦法讓cout成為第一個(gè)參數(shù),怎么做呢?
把函數(shù)重載寫到類外面不就行了是吧。
沒(méi)有說(shuō)運(yùn)算符重載不能寫到類外面啊,我們寫到類里面是為了啥,是不是只是為了可以訪問(wèn)private修飾的成員變量啊

那我們現(xiàn)在重載到外面:

在這里插入圖片描述
那現(xiàn)在面臨的問(wèn)題是啥?
是在類外不能訪問(wèn)私有的成員變量,那怎么辦?
可以把成員變量變成共有的public,但這樣是不是就不能很好的保證封裝性了;
或者可以提供Get方法,但C++一般不喜歡這樣搞。
那還有什么方法呢?
🆗,就是用友元函數(shù)
那怎么做呢?
我們把函數(shù)聲明再放到類里面一份,但在前面加一個(gè)friend就行了:
在這里插入圖片描述

那這下我們就可以正常使用<<了:
在這里插入圖片描述

但是呢:
在這里插入圖片描述

這里不支持連續(xù)的流插入。為什么呢?
因?yàn)槲覀冎剌d的沒(méi)有返回值
在這里插入圖片描述
那應(yīng)該返回啥?
是不是返回cout呀,讓它能夠繼續(xù)打印后面的。
我們看其實(shí)庫(kù)里面就是這么搞的:
在這里插入圖片描述

ostream& operator<<(ostream& out, Date& d)
{out << d._year << "-" << d._month << "-" << d._day << endl;return out;
}

在這里插入圖片描述

這樣就行了。

8. 流提取>>重載

那緊接著,我們?cè)賮?lái)重載一下流提取:

istream& operator>>(istream& in, Date& d)
{in >> d._year >> d._month >> d._day;return in;
}

測(cè)試一下:
在這里插入圖片描述
就完成了。

9. 總結(jié)

那最后呢,還要給大家說(shuō)明一點(diǎn):

我們?cè)谥暗?strong>類和對(duì)象第一篇其實(shí)就提到了:
在這里插入圖片描述
就是類的成員函數(shù)如果直接定義在類里面,編譯器是會(huì)將其當(dāng)成內(nèi)聯(lián)函數(shù)的,不管你有沒(méi)有加inline關(guān)鍵字。

那我們?cè)趯W(xué)習(xí)內(nèi)聯(lián)函數(shù)的時(shí)候也說(shuō)了:

一般建議將函數(shù)規(guī)模較小(即函數(shù)不是很長(zhǎng),具體沒(méi)有準(zhǔn)確的說(shuō)法,取決于編譯器內(nèi)部實(shí)現(xiàn))、不是遞歸、且頻繁調(diào)用的函數(shù)實(shí)現(xiàn)成內(nèi)聯(lián)函數(shù)。
所以說(shuō),類里面的成員函數(shù)如果規(guī)模較小,適合做內(nèi)聯(lián)函數(shù)的,直接定義在類里面。

不過(guò)我們今天寫的這個(gè)日期類,里面我是所有成員函數(shù)的聲明和定義都分離了,大家以后可以根據(jù)實(shí)際情況,有些成員函數(shù)直接定義在類里面。
但是我們說(shuō)了內(nèi)聯(lián)函數(shù)不是只是對(duì)編譯器的一個(gè)建議嘛,如果規(guī)模較大的函數(shù)就算我們實(shí)現(xiàn)成內(nèi)聯(lián)函數(shù)編譯器也不一定按照內(nèi)聯(lián)函數(shù)處理。
那在類里面也是這樣,就算我們把全部的類成員函數(shù)都直接定義在類里面,也不一定會(huì)全部當(dāng)做內(nèi)聯(lián)函數(shù)處理,編譯器也還是會(huì)看它具體適不適合做內(nèi)聯(lián)。

另外還有一點(diǎn):

上一篇文章我們不是還學(xué)習(xí)了const成員函數(shù)嘛,大家還可以看一看我們?nèi)掌陬惖倪@么多成員函數(shù),哪一個(gè)在函數(shù)內(nèi)部不需要改變調(diào)用它的對(duì)象,是不是把它實(shí)現(xiàn)成const成員函數(shù)也是比較好的。

10. 源碼展示

最后,把完整的源碼給大家展示一下:

  1. Date.h
#pragma once
#include <iostream>
#include <stdbool.h>
#include <assert.h>
using namespace std;class Date
{//友元friend ostream& operator<<(ostream& out, const Date& d);friend istream& operator>>(istream& in, Date& d);public:int GetMonthDay(int year, int month);//構(gòu)造函數(shù)Date(int year = 1, int month = 1, int day = 1);//拷貝構(gòu)造函數(shù)//Date(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);void Print();bool operator==(const Date& d);Date& operator+=(int day);Date operator+(int day);//前置++Date& operator++();//后置++Date operator++(int);Date& operator-=(int day);Date operator-(int day);Date& operator--();Date operator--(int);//日期-日期int operator-(Date d);//賦值重載(對(duì)于Date類用默認(rèn)生成的就行)//d1=d2(this就是d1,d就是d2)/*Date& operator=(const Date& d){if (this != &d){_year = d._year;_month = d._month;_day = d._day;}return *this;}*/
private:int _year;int _month;int _day;
};
//<<
ostream& operator<<(ostream& out, const Date& d);
istream& operator>>(istream& in, Date& d);
  1. Date.cpp
#define _CRT_SECURE_NO_WARNINGS
#include "Date.h"int Date::GetMonthDay(int year, int month)
{assert(month > 0 && month < 13);int MonthArr[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;}else{return MonthArr[month];}
}
//構(gòu)造函數(shù)
Date::Date(int year, int month, int day)
{if (month > 0 && month < 13 && day>0 && day <= GetMonthDay(year, month)){_year = year;_month = month;_day = day;}else{cout << "日期非法" << endl;_year = 1;_month = 1;_day = 1;}
}
//拷貝構(gòu)造函數(shù)
//Date::Date(const Date& d)
//{
//	_year = d._year;
//	_month = d._month;
//	_day = d._day;
//}
bool Date::operator<(const Date& d)
{if (_year < d._year)return true;else if (_year == d._year && _month < d._month)return true;else if (_year == d._year && _month == d._month && _day < d._day)return true;return false;
}
bool Date::operator<=(const Date& d)
{return *this == d || *this < d;
}
bool Date::operator>(const Date& d)
{return !(*this <= d);
}
bool Date::operator>=(const Date& d)
{return !(*this < d);
}
bool Date::operator!=(const Date& d)
{return !(*this == d);
}
void Date::Print()
{cout << _year << "-" << _month << "-" << _day << endl;
}
bool Date::operator==(const Date& d)
{return _year == d._year&& _month == d._month&& _day == d._day;
}//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)
//{
//	*this = *this + day;
//	return *this;
//}Date& Date::operator+=(int day)
{if (day < 0){*this -= -day;return *this;}_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++()
{*this += 1;return *this;
}
//后置++
Date Date::operator++(int)
{Date tmp(*this);*this += 1;return tmp;
}
Date& Date::operator-=(int day)
{if (day < 0){*this += -day;return *this;}_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;
}Date& Date::operator--()
{*this -= 1;return *this;
}
Date Date::operator--(int)
{Date tmp(*this);*this -= 1;return tmp;
}
//日期-日期
int Date::operator-(Date d)
{Date max = *this;Date min = d;int flag = 1;if (*this < d){max = d;min = *this;flag = -1;}int n = 0;while (min != max){++min;++n;}return n * flag;
}
//<<
ostream& operator<<(ostream& out, const Date& d)
{out << d._year << "-" << d._month << "-" << d._day << endl;return out;
}
istream& operator>>(istream& in, Date& d)
{in >> d._year >> d._month >> d._day;return in;
}
  1. Test.cpp
#define _CRT_SECURE_NO_WARNINGS
#include "Date.h"void Datetest1()
{Date d1(2023, 2, 15);d1.Print();Date d2 = d1 + (-100);d2.Print();/*Date d3 = ++d1;d3.Print();*/
}
void Datetest2()
{Date d1(2023, 2, 16);d1.Print();Date d2 = d1--;d1.Print();d2.Print();}
void Datetest3()
{Date d1;cin >> d1;cout << d1 << endl;}
int main()
{//Datetest3();return 0;
}

🆗,那這篇文章就到這里,歡迎大家指正!!!
下一篇文章,我們會(huì)對(duì)類和對(duì)象再做一些補(bǔ)充和收尾!!!
在這里插入圖片描述

http://www.risenshineclean.com/news/36361.html

相關(guān)文章:

  • 網(wǎng)絡(luò)推廣和網(wǎng)站推廣平臺(tái)網(wǎng)站推廣的幾種方法
  • b2b網(wǎng)站開發(fā)搜索引擎營(yíng)銷sem
  • 網(wǎng)頁(yè)制作工具常見(jiàn)的有哪些太原百度快速優(yōu)化
  • 用爬蟲做網(wǎng)站如何查看一個(gè)網(wǎng)站的訪問(wèn)量
  • 網(wǎng)站開發(fā)技術(shù)的現(xiàn)狀及發(fā)展趨勢(shì)百度快照怎么刪除
  • 沈陽(yáng)外貿(mào)網(wǎng)站建設(shè)寧波seo免費(fèi)優(yōu)化軟件
  • 做網(wǎng)站和程序員哪個(gè)好點(diǎn)電商運(yùn)營(yíng)培訓(xùn)班多少錢
  • 做網(wǎng)站需要獨(dú)立顯卡嗎成都網(wǎng)多多
  • 手機(jī)上如何做網(wǎng)站湖南靠譜seo優(yōu)化
  • 建筑招聘網(wǎng)站哪個(gè)好網(wǎng)站建設(shè)排名優(yōu)化
  • 網(wǎng)站建設(shè)待遇怎樣長(zhǎng)尾關(guān)鍵詞挖掘熊貓
  • 手機(jī)網(wǎng)站模板免費(fèi)電子商務(wù)網(wǎng)站建設(shè)多少錢
  • 住房和城鄉(xiāng)建設(shè)部網(wǎng)站證書查詢百度服務(wù)商
  • 上海 有哪些做網(wǎng)站的公司好想做游戲推廣怎么找游戲公司
  • 免費(fèi)一級(jí)域名網(wǎng)站西安百度框架戶
  • 職業(yè)生涯規(guī)劃大賽的意義短視頻seo系統(tǒng)
  • 給別人建網(wǎng)站工作行嗎廣告開戶
  • 網(wǎng)站建設(shè)維護(hù)及使用管理辦法深圳seo優(yōu)化公司哪家好
  • 南陽(yáng)政府做網(wǎng)站推廣嗎網(wǎng)站推廣策劃報(bào)告
  • b2c網(wǎng)站建設(shè) 模板搜索引擎關(guān)鍵詞優(yōu)化方案
  • 發(fā)布培訓(xùn)的免費(fèi)網(wǎng)站模板產(chǎn)品網(wǎng)絡(luò)推廣的方法
  • 做網(wǎng)站被騙了怎么辦搭建網(wǎng)站工具
  • 蕪湖市建設(shè)工程質(zhì)量監(jiān)督站網(wǎng)站百度推廣的方式有哪些
  • 個(gè)體戶 做網(wǎng)站個(gè)人網(wǎng)頁(yè)生成器
  • 濰坊做網(wǎng)站建設(shè)站長(zhǎng)seo工具
  • 圖片展示 網(wǎng)站線上平臺(tái)推廣方案
  • 中國(guó)建設(shè)網(wǎng)站用戶名上海專業(yè)的seo公司
  • 無(wú)錫高端網(wǎng)站建設(shè)咨詢磁力王
  • 網(wǎng)頁(yè)設(shè)計(jì)網(wǎng)站教程打廣告
  • 國(guó)內(nèi)最好的軟件網(wǎng)站建設(shè)關(guān)鍵詞優(yōu)化話術(shù)