版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
第基于C++實(shí)現(xiàn)日期計(jì)算器的詳細(xì)教程目錄一、前言二、日期類的實(shí)現(xiàn)檢查日期的合法性運(yùn)算符重載==運(yùn)算符重載=運(yùn)算符重載運(yùn)算符重載=運(yùn)算符重載!=運(yùn)算符重載改進(jìn)和優(yōu)化日期+天數(shù)日期+=天數(shù)日期-=天數(shù)日期-天數(shù)前置++后置++前置--后置--日期-日期三、總結(jié)
一、前言
在我們的日常生活中,我們可能需要計(jì)算幾天后的日期,或計(jì)算日期差等,現(xiàn)如今計(jì)算日期的方式有很多,簡單粗暴的直接查看日歷,快捷點(diǎn)的直接使用日期計(jì)算器來求得,先給一個(gè)網(wǎng)絡(luò)上的日期計(jì)算器截圖:
現(xiàn)在,就讓我們用代碼來實(shí)現(xiàn)其工作原理吧。
注意:本篇日期類.h文件放聲明,.cpp文件放定義
二、日期類的實(shí)現(xiàn)
檢查日期的合法性
實(shí)現(xiàn)日期類首先就得檢查日期的合法性,這其中就包括大小月,閏年的2月有29天,一年只有12個(gè)月等等細(xì)節(jié)都要考慮到。
classDate
public:
boolisLeapYear(intyear)//判斷是否為閏年
//四年一閏百年不閏或四百年一閏
return(year%4==0year%100!=0)||(year%400==0);
staticintGetMonthDay(intyear,intmonth)
//加上static防止函數(shù)頻繁調(diào)用開辟幾十個(gè)字節(jié)大小的數(shù)組,最好加上
intmonthDayArray[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
if(month==2isLeapYear(year))
return29;//閏月29天
else
returnmonthDayArray[month];
Date(intyear=1,intmonth=1,intday=1)
if(year=1month=12month=1day=GetMonthDay(year,month))
//確保日期合法
_year=year;
_month=month;
_day=day;
private:
int_year;
int_month;
int_day;
};
運(yùn)算符重載
思路:
運(yùn)算符重載在我上一篇博文已經(jīng)詳細(xì)講解過,主要是先把大于的情況全部統(tǒng)計(jì)出來,就比如我要比較實(shí)例化對象d1是否小于實(shí)例化對象d2,只需考慮如下三種滿足的情況:
d1的年小于d2的年d1與d2年相等,d1的月小于d2的月d1與d2年相等月相等,d1的天小于d2的天
這三種全是小于的情況,返回true,其余返回false
代碼如下:
//運(yùn)算符重載
boolDate::operator(constDated)const//類外訪問成員函數(shù)需要設(shè)定類域
if(_yeard._year||
_year==d._year_monthd._month||
_year==d._year_month==d._month_dayd._day)
returntrue;
else
returnfalse;
}
==運(yùn)算符重載
思路:
==運(yùn)算符重載其實(shí)非常簡單,只需要判斷d1和d2的年、月、天是否對應(yīng)相等即可:
代碼如下:
//==運(yùn)算符重載
boolDate::operator==(constDated)const
return_year==d._year
_month==d._month
_day==d._day;
}
=運(yùn)算符重載
思路:--復(fù)用
=的運(yùn)算符重載,這里要仔細(xì)想一想=成立的條件是啥。不就是要么要么=嗎?我們只需要復(fù)用先前寫的運(yùn)算符重載和=運(yùn)算符重載,無需自己費(fèi)老大勁推導(dǎo)其內(nèi)部原理。
代碼如下:
//=運(yùn)算符重載
boolDate::operator=(constDated)const
return*thisd||*this==d;
}
運(yùn)算符重載
思路:--復(fù)用
的反義就是=,所以我們只需要復(fù)用=運(yùn)算符重載,再對其取反即可解決此問題。
代碼如下:
//運(yùn)算符重載
boolDate::operator(constDated)const
return!(*this=d);
}
=運(yùn)算符重載
思路:--復(fù)用
=的反義就是,所以我們只需要復(fù)用運(yùn)算符重載,再對其取反即可。
代碼如下:
//=運(yùn)算符重載
boolDate::operator=(constDated)const
return!(*this
}
!=運(yùn)算符重載
思路:--復(fù)用
有了前面的基礎(chǔ),寫個(gè)!=也很簡單,對==取反即可
代碼如下:
//!=運(yùn)算符重載
boolDate::operator!=(constDated)const
return!(*this==d);
}
改進(jìn)和優(yōu)化
上述我們寫的運(yùn)算符重載都是建立在聲明定義分離的,這里我們可以對其進(jìn)行優(yōu)化,如下:
先前我們學(xué)過內(nèi)聯(lián),可以幫助我們對于短小函數(shù)減少函數(shù)調(diào)用而引發(fā)的效率損失問題,因此我們可以把上述幾個(gè)運(yùn)算符重載函數(shù)放成內(nèi)聯(lián),此外,有一種簡單粗暴的方法:直接在類里定義,因?yàn)轭惱锏暮瘮?shù)默認(rèn)內(nèi)聯(lián),還省的我們自己寫inline,而且我們也不用在類外加上類域了,當(dāng)然,有些長的函數(shù)還是聲明和定義分離比較好。
Date.h文件:
#pragmaonce
#includeiostream
#includeassert.h
usingstd::cout;
usingstd::cin;
usingstd::endl;
classDate
public:
boolisLeapYear(intyear)
//四年一潤百年不潤或四百年一潤
return(year%4==0year%100!=0)||(year%400==0);
//獲取某月天數(shù)
intGetMonthDay(intyear,intmonth);
//構(gòu)造函數(shù)
Date(intyear=1,intmonth=1,intday=1);
//打印
voidPrint()const
cout_year"-"_month"-"_dayendl;
//運(yùn)算符重載
booloperator(constDated)const;
//==運(yùn)算符重載
booloperator==(constDated)const;
//=運(yùn)算符重載
booloperator=(constDated)const
return*thisd||*this==d;
//運(yùn)算符重載
booloperator(constDated)const
return!(*this=d);
//return(d*this);
//=運(yùn)算符重載
booloperator=(constDated)const
return!(*this
//!=運(yùn)算符重載
booloperator!=(constDated)const
return!(*this==d);
private:
int_year;
int_month;
int_day;
};
Date.cpp文件:
#include"Date.h"
//獲取某月天數(shù)
intDate::GetMonthDay(intyear,intmonth)
assert(year=0month0month13);
staticintmonthDayArray[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
if(month==2isLeapYear(year))
return29;
else
returnmonthDayArray[month];
//構(gòu)造函數(shù)
Date::Date(intyear,intmonth,intday)
if(year=1month=12month=1day=GetMonthDay(year,month))
_year=year;
_month=month;
_day=day;
else
cout"日期非法"endl;
//運(yùn)算符重載
boolDate::operator(constDated)const//類外訪問成員函數(shù)需要設(shè)定類域
if(_yeard._year||
_year==d._year_monthd._month||
_year==d._year_month==d._month_dayd._day)
returntrue;
else
returnfalse;
//==運(yùn)算符重載
boolDate::operator==(constDated)const
return_year==d._year
_month==d._month
_day==d._day;
}
日期+天數(shù)
思路:
對于日期+天數(shù),我們得到的還是一個(gè)日期。特別需要注意進(jìn)位的問題(天滿了往月進(jìn),月滿了往年進(jìn)),主要考慮如下幾個(gè)特殊點(diǎn):
加過的天數(shù)超過該月的最大天數(shù),需要進(jìn)位
當(dāng)月進(jìn)位到13時(shí),年進(jìn)位+1,月置為1
法一:
DateDate::operator+(intday)const
Dateret(*this);//拷貝構(gòu)造,拿d1去初始化ret
ret._day+=day;
while(ret._dayGetMonthDay(ret._year,ret._month))
ret._day-=GetMonthDay(ret._year,ret._month);
ret._month++;
if(ret._month==13)
ret._year++;
ret._month=1;
returnret;
}
出了作用域,對象ret不在,它是一個(gè)局部對象,我們這里不能用引用,用了的話,返回的就是ret的別名,但是ret又已經(jīng)銷毀了,訪問野指針了,所以出了作用域,如果對象不在了,就不能用引用返回,要用傳值返回
法二:復(fù)用日期+=天數(shù)
此法是建立在日期+=天數(shù)的基礎(chǔ)上完成的,這里各位可以先看下文日期+=天數(shù),然后我們進(jìn)行復(fù)用:
DateDate::operator+(intday)const
//法二:復(fù)用日期+=天數(shù)
Dateret(*this);
ret+=day;
returnret;
}
法一和法二熟優(yōu)?
答案:法二更好,也就是用+去復(fù)用+=,具體原因在下文會(huì)解釋。
日期+=天數(shù)
這里實(shí)現(xiàn)+=其實(shí)有兩種方案
法一:
前面我實(shí)現(xiàn)的日期+天數(shù),仔細(xì)觀察我的代碼,函數(shù)的第一行,我就調(diào)用了一個(gè)拷貝構(gòu)造:
Dateret(*this);//拷貝構(gòu)造,拿d1去初始化ret
這里調(diào)用拷貝構(gòu)造,是為了不在*this本身上做變動(dòng),只在ret上進(jìn)行操作,其理由是日期+天數(shù)得到的是另一個(gè)日期,而不用拷貝構(gòu)造直接在*this上做改動(dòng)只會(huì)導(dǎo)致原有的日期也變化,而這個(gè)變化正是我日期+=天數(shù)的需求
仔細(xì)想想:+=天數(shù)就是在原有的日期上再加一定的天數(shù),直接對*this做手腳即可,因此只需對日期+天數(shù)的代碼進(jìn)行小改動(dòng)即可:
DateDate::operator+=(intday)//傳引用返回
//如果day小于0,要單獨(dú)處理
if(day0)
return*this-=-day;
_day+=day;
while(_dayGetMonthDay(_year,_month))
_day-=GetMonthDay(_year,_month);
_month++;
if(_month==13)
_year++;
_month=1;
return*this;
}
注意這里是傳引用返回,原因就在于我返回的*this是全局的,出了作用域還在
法二:復(fù)用日期+天數(shù)
DateDate::operator+=(intday)
//法二:復(fù)用
*this=*this+day;//讓d1+過天數(shù)后再返回給自己從而實(shí)現(xiàn)+=
return*this;
}
法一和法二熟優(yōu)?
答案:法一。其實(shí)討論這個(gè)問題就是在討論用+去復(fù)用+=號還是用+=復(fù)用+號,答案是用+去復(fù)用+=好,因?yàn)?有兩次拷貝,而+=沒有拷貝,所以實(shí)現(xiàn)+=,并且用+去復(fù)用+=效率更高
日期-=天數(shù)
思路:
日期-=天數(shù)得到的還是一個(gè)日期,且是在原日期的基礎(chǔ)上做改動(dòng)。合法的日期減去天數(shù)后的day只要0就沒問題,若小于0就要借位了。要注意當(dāng)減去的天數(shù)0時(shí)單獨(dú)討論。具體步驟如下:
當(dāng)減的天數(shù)為負(fù)數(shù),則為+=,直接調(diào)用若減后的day0,月-1若月=0,則年-1,月置為12
代碼如下:
//日期-=天數(shù)d1-=100
DateDate::operator-=(intday)
//如果減去的天數(shù)是負(fù)數(shù),要單獨(dú)處理,直接調(diào)用+=運(yùn)算符重載
if(day0)
return*this+=-day;
_day-=day;
while(_day=0)
--_month;
if(_month==0)
_month=12;
--_year;
_day+=GetMonthDay(_year,_month);
return*this;
}
日期-天數(shù)
有了先前日期+和+=的基礎(chǔ),這里實(shí)現(xiàn)日期-天數(shù)直接復(fù)用日期-=天數(shù)即可:
//日期-天數(shù)
DateDate::operator-(intday)const
Dateret(*this);
ret-=day;
returnret;
}
前置++
思路:
C++里有前置++和后置++,這就導(dǎo)致一個(gè)巨大的問題,該如何區(qū)分它們,具體實(shí)現(xiàn)過程不難(直接復(fù)用+=即可),難的是如何區(qū)分前置和后置。因此C++規(guī)定,無參的為前置,有參的為后置。
代碼如下:
//前置++
DateDate::operator++()//無參的為前置
*this+=1;//直接復(fù)用+=
return*this;
}
后置++
思路:
有參的即為后置,后置++拿到的返回值應(yīng)該是自己本身未加過的,因此要先把自己保存起來,再++*this,隨后返回自己。
代碼如下:
//后置++
DateDate::operator++(inti)//有參數(shù)的為后置
Datetmp(*this);
*this+=1;//復(fù)用+=
returntmp;
}
前置--
思路:
前置--和前置++沒啥區(qū)別,只不過內(nèi)部復(fù)用的是-=
代碼如下:
//前置--
DateDate::operator--()//無
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 中學(xué)學(xué)生社團(tuán)活動(dòng)經(jīng)費(fèi)預(yù)算制度
- 養(yǎng)老院定期體檢制度
- 企業(yè)內(nèi)部保密工作責(zé)任追究制度
- 公共交通車輛安全檢查制度
- 2026年工業(yè)制造中的6S管理與效率提升題解
- 2026年公務(wù)員考試模擬題行政職業(yè)能力測驗(yàn)與申論練習(xí)
- 2026年航空航天基礎(chǔ)知識學(xué)習(xí)入門與實(shí)踐題庫
- 2026年體育訓(xùn)練與健康管理測試題目
- 2026年企業(yè)管理實(shí)務(wù)能力測試題
- 2026年版權(quán)侵權(quán)監(jiān)測協(xié)議(實(shí)時(shí)·發(fā)現(xiàn)版)
- 2026中國電信四川公用信息產(chǎn)業(yè)有限責(zé)任公司社會(huì)成熟人才招聘備考題庫及答案詳解(奪冠系列)
- 學(xué)堂在線 雨課堂 學(xué)堂云 莊子哲學(xué)導(dǎo)讀 章節(jié)測試答案
- 23G409先張法預(yù)應(yīng)力混凝土管樁
- 《配電網(wǎng)設(shè)施可靠性評價(jià)指標(biāo)導(dǎo)則》
- 街道(鄉(xiāng)鎮(zhèn))區(qū)域養(yǎng)老服務(wù)中心建設(shè)驗(yàn)收指標(biāo)總分表及驗(yàn)收標(biāo)準(zhǔn)
- 國家衛(wèi)生部《綜合醫(yī)院分級管理標(biāo)準(zhǔn)》
- 預(yù)防兩癌知識講座
- 人教版九年級數(shù)學(xué)第二十四章《圓》單元知識點(diǎn)總結(jié)
- 西班牙語專業(yè)本科論文模板
- GB/T 42288-2022電化學(xué)儲(chǔ)能電站安全規(guī)程
- 地質(zhì)災(zāi)害治理工程用表格(完整資料)
評論
0/150
提交評論