基于C++實(shí)現(xiàn)一個(gè)日期計(jì)算器
一、日期計(jì)算器的功能
實(shí)現(xiàn)日期類的==、!=、+=、+、-=、-、>=、>、<=、<、前置++和--、后置++和--。
二、獲取每個(gè)月的天數(shù)
int GetMonthDay(int year, int month) { //靜態(tài)數(shù)組,每次調(diào)用不用頻繁在棧區(qū)創(chuàng)建數(shù)組 static int monthArr[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 }; //判斷是否閏年 int day = monthArr[month - 1]; if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)) { day = 29; } return day; }
1、因?yàn)镚etMonthDay這個(gè)函數(shù)需要在日期類中被頻繁調(diào)用,所以將 monthArr存放至靜態(tài)區(qū),減少數(shù)組頻繁開辟、銷毀空間的開銷。
三、Date類中的默認(rèn)成員函數(shù)
1、構(gòu)造函數(shù)
Date(int year = 1, int month = 1, int day = 1) { if (year >= 1 && month >= 1 && day >= 1 && day <= GetMonthDay(year, month)) { _year = year; _month = month; _day = day; //cout << "構(gòu)造成功" << endl; } else { cout << "日期不合法" << endl; } }
日期類的構(gòu)造函數(shù)需要對(duì)日期的的合法性進(jìn)行判斷。
2、析構(gòu)函數(shù)
~Date()//可不寫 { ; }
日期類因?yàn)闆]有申請(qǐng)資源(動(dòng)態(tài)開辟空間、文件的打開等),所以無需寫析構(gòu)函數(shù),系統(tǒng)默認(rèn)生成的就可以。
3、拷貝構(gòu)造
Date(const Date& d)//可不寫 { _year = d._year; _month = d._month; _day = d._day; //cout << "拷貝構(gòu)造成功" << endl; }
系統(tǒng)默認(rèn)生成的拷貝構(gòu)造函數(shù)會(huì)對(duì)內(nèi)置類型完成淺拷貝,所以內(nèi)置類型也可以不用寫,用系統(tǒng)默認(rèn)生成的就可以。
4、賦值運(yùn)算符重載
Date& operator=(Date& d) { _year = d._year; _month = d._month; _day = d._day; //cout << "賦值成功" << endl; return *this; }
也可不寫,使用系統(tǒng)默認(rèn)生成的即可。
拷貝構(gòu)造和賦值運(yùn)算符重載的區(qū)別在于拷貝構(gòu)造用于對(duì)象構(gòu)造時(shí)使用,而賦值運(yùn)算符重載用于已存在對(duì)象賦值時(shí)使用。
四、運(yùn)算符重載
1、+=、+、-=、-
Date& operator+=(int day) { if (day < 0) *this -= -day; else { _day += day; while (_day > GetMonthDay(_year, _month)) { _day -= GetMonthDay(_year, _month); ++_month; if (_month > 12) { _month = 1; ++_year; } } } return *this; } Date operator+(int day) { Date tmp(*this); return tmp += day; } Date& operator-=(int day) { if (day < 0) *this += -day; else { _day -= day; while (_day <= 0) { --_month; if (_month <= 0) { _month = 12; --_year; } _day += GetMonthDay(_year, _month); } } return *this; } Date operator-(int day) { Date tmp(*this); return tmp -= day; } //日期減日期 int operator-(const Date& d) { Date tmpThis = *this, tmpDay = d; int count = 0;//用于計(jì)數(shù) if (*this >= d) { while (tmpDay != tmpThis) { ++tmpDay; ++count; } } else { while (tmpDay != tmpThis) { ++tmpThis; --count; } } return count; }
1、注意這幾個(gè)運(yùn)算符要防止外部傳入的day是負(fù)數(shù)。例如+=傳入的參數(shù)如果是負(fù)數(shù),則去調(diào)用-=函數(shù)。
2、注意傳值返回和傳引用返回,當(dāng)return對(duì)象出了作用域還存在時(shí),可以用傳引用返回,減少一次拷貝構(gòu)造。
3、實(shí)現(xiàn)完+=、-=后,+、-運(yùn)算符可復(fù)用邏輯。
2、==、!=、>、>=、<、<=
bool operator==(const Date& d) { if (_year == d._year && _month == d._month && _day == d._day) { return true; } return false; } bool operator>(const Date& d) { if (_year > d._year) return true; if (_year == d._year && _month > d._month) return true; 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); }
1、注意右操組數(shù)一定要加上&,減少一次傳參時(shí)的拷貝構(gòu)造;再加上const,防止被引用的對(duì)象被改變。
2、寫完==和>函數(shù),其他運(yùn)算符都可以復(fù)用邏輯。
3、前置++和--、后置++和--
Date& operator++() { ++_day; if (_day > GetMonthDay(_year, _month)) { _day = 1; ++_month; if (_month > 12) { _month = 1; ++_year; } } return *this; } Date operator++(int) { Date tmp(*this); ++* this; return tmp; } Date& operator--() { --_day; if (_day <= 0) { --_month; if (_month == 0) { _month = 12; --_year; } _day += GetMonthDay(_year, _month); } return *this; } Date operator--(int) { Date tmp(*this); --* this; return tmp; }
1、因?yàn)?+和--是單操作數(shù)的運(yùn)算符,在重載時(shí),無法區(qū)分是前置的重載還是后置的重載,所以C++規(guī)定:前置重載與普通運(yùn)算符重載一致,后置重載需要在參數(shù)列表中加入一個(gè)無用的參數(shù)。這個(gè)參數(shù)必須是int類型(用別的類型編譯器報(bào)錯(cuò))。
2、前置++--可以使用傳引用返回,但后置++--因?yàn)榉祷刂禃簳r(shí)不改變,所以只能傳值返回。這也是使用前置++--性能優(yōu)于后置++--的原因。
五、日期類代碼
class Date { public: void Print() { cout << _year << " " << _month << " " << _day << endl; } int GetMonthDay(int year, int month) { //靜態(tài)數(shù)組,每次調(diào)用不用頻繁在棧區(qū)創(chuàng)建數(shù)組 static int monthArr[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 }; //判斷是否閏年 int day = monthArr[month - 1]; if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)) { day = 29; } return day; } //構(gòu)造函數(shù) Date(int year = 1, int month = 1, int day = 1) { if (year >= 1 && month >= 1 && day >= 1 && day <= GetMonthDay(year, month)) { _year = year; _month = month; _day = day; //cout << "構(gòu)造成功" << endl; } else { cout << "日期不合法" << endl; } } //析構(gòu)函數(shù) ~Date() { cout << "析構(gòu)成功" << endl;; } //拷貝構(gòu)造 Date(const Date& d) { _year = d._year; _month = d._month; _day = d._day; cout << "拷貝構(gòu)造成功" << endl; } ////賦值運(yùn)算符重載 Date& operator=(Date& d) { _year = d._year; _month = d._month; _day = d._day; cout << "賦值成功" << endl; return *this; } //運(yùn)算符重載 Date& operator+=(int day) { if (day < 0) *this -= -day; else { _day += day; while (_day > GetMonthDay(_year, _month)) { _day -= GetMonthDay(_year, _month); ++_month; if (_month > 12) { _month = 1; ++_year; } } } return *this; } Date operator+(int day) { Date tmp(*this); return tmp += day; } Date& operator-=(int day) { if (day < 0) *this += -day; else { _day -= day; while (_day <= 0) { --_month; if (_month <= 0) { _month = 12; --_year; } _day += GetMonthDay(_year, _month); } } return *this; } Date operator-(int day) { Date tmp(*this); return tmp -= day; } int operator-(const Date& d) { Date tmpThis = *this, tmpDay = d; int count = 0;//用于計(jì)數(shù) if (*this >= d) { while (tmpDay != tmpThis) { ++tmpDay; ++count; } } else { while (tmpDay != tmpThis) { ++tmpThis; --count; } } return count; } bool operator==(const Date& d) { if (_year == d._year && _month == d._month && _day == d._day) { return true; } return false; } bool operator>(const Date& d) { if (_year > d._year) return true; if (_year == d._year && _month > d._month) return true; 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); } Date& operator++() { ++_day; if (_day > GetMonthDay(_year, _month)) { _day = 1; ++_month; if (_month > 12) { _month = 1; ++_year; } } return *this; } Date operator++(int) { Date tmp(*this); ++* this; return tmp; } Date& operator--() { --_day; if (_day <= 0) { --_month; if (_month == 0) { _month = 12; --_year; } _day += GetMonthDay(_year, _month); } return *this; } Date operator--(int) { Date tmp(*this); --* this; return tmp; } private: int _year; int _month; int _day; };
因?yàn)楹瘮?shù)的聲明和定義全部放在類中,會(huì)被編譯器當(dāng)成內(nèi)聯(lián)函數(shù)處理。所以可以根據(jù)自身需要,將部分調(diào)用不頻繁、稍長(zhǎng)的函數(shù)的聲明寫在類中,而定義寫在類外。
到此這篇關(guān)于基于C++實(shí)現(xiàn)一個(gè)日期計(jì)算器的文章就介紹到這了,更多相關(guān)C++日期計(jì)算器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++如何實(shí)現(xiàn)BCD碼和ASCII碼的相互轉(zhuǎn)換
這篇文章主要介紹了C++實(shí)現(xiàn)BCD碼和ASCII碼互轉(zhuǎn),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06C語言數(shù)據(jù)結(jié)構(gòu)之二叉樹的非遞歸后序遍歷算法
這篇文章主要介紹了C語言數(shù)據(jù)結(jié)構(gòu)之二叉樹的非遞歸后序遍歷算法的相關(guān)資料,希望通過本文能幫助到大家,讓大家實(shí)現(xiàn)這樣的功能,需要的朋友可以參考下2017-10-10VC實(shí)現(xiàn)給窗體的一個(gè)按鈕添加事件的方法
這篇文章主要介紹了VC實(shí)現(xiàn)給窗體的一個(gè)按鈕添加事件的方法,通過三個(gè)簡(jiǎn)單步驟實(shí)現(xiàn)窗體按鈕添加事件,需要的朋友可以參考下2015-05-05