網站首頁 編程語言 正文
一、日期計算器的功能
實現日期類的==、!=、+=、+、-=、-、>=、>、<=、<、前置++和--、后置++和--。
二、獲取每個月的天數
int GetMonthDay(int year, int month)
{
//靜態數組,每次調用不用頻繁在棧區創建數組
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、因為GetMonthDay這個函數需要在日期類中被頻繁調用,所以將 monthArr存放至靜態區,減少數組頻繁開辟、銷毀空間的開銷。
三、Date類中的默認成員函數
1、構造函數
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 << "構造成功" << endl;
}
else
{
cout << "日期不合法" << endl;
}
}
日期類的構造函數需要對日期的的合法性進行判斷。
2、析構函數
~Date()//可不寫
{
;
}
日期類因為沒有申請資源(動態開辟空間、文件的打開等),所以無需寫析構函數,系統默認生成的就可以。
3、拷貝構造
Date(const Date& d)//可不寫
{
_year = d._year;
_month = d._month;
_day = d._day;
//cout << "拷貝構造成功" << endl;
}
系統默認生成的拷貝構造函數會對內置類型完成淺拷貝,所以內置類型也可以不用寫,用系統默認生成的就可以。
4、賦值運算符重載
Date& operator=(Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
//cout << "賦值成功" << endl;
return *this;
}
也可不寫,使用系統默認生成的即可。
拷貝構造和賦值運算符重載的區別在于拷貝構造用于對象構造時使用,而賦值運算符重載用于已存在對象賦值時使用。
四、運算符重載
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;//用于計數
if (*this >= d)
{
while (tmpDay != tmpThis)
{
++tmpDay;
++count;
}
}
else
{
while (tmpDay != tmpThis)
{
++tmpThis;
--count;
}
}
return count;
}
1、注意這幾個運算符要防止外部傳入的day是負數。例如+=傳入的參數如果是負數,則去調用-=函數。
2、注意傳值返回和傳引用返回,當return對象出了作用域還存在時,可以用傳引用返回,減少一次拷貝構造。
3、實現完+=、-=后,+、-運算符可復用邏輯。
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、注意右操組數一定要加上&,減少一次傳參時的拷貝構造;再加上const,防止被引用的對象被改變。
2、寫完==和>函數,其他運算符都可以復用邏輯。
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、因為++和--是單操作數的運算符,在重載時,無法區分是前置的重載還是后置的重載,所以C++規定:前置重載與普通運算符重載一致,后置重載需要在參數列表中加入一個無用的參數。這個參數必須是int類型(用別的類型編譯器報錯)。
2、前置++--可以使用傳引用返回,但后置++--因為返回值暫時不改變,所以只能傳值返回。這也是使用前置++--性能優于后置++--的原因。
五、日期類代碼
class Date
{
public:
void Print()
{
cout << _year << " " << _month << " " << _day << endl;
}
int GetMonthDay(int year, int month)
{
//靜態數組,每次調用不用頻繁在棧區創建數組
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;
}
//構造函數
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 << "構造成功" << endl;
}
else
{
cout << "日期不合法" << endl;
}
}
//析構函數
~Date()
{
cout << "析構成功" << endl;;
}
//拷貝構造
Date(const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
cout << "拷貝構造成功" << endl;
}
////賦值運算符重載
Date& operator=(Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
cout << "賦值成功" << endl;
return *this;
}
//運算符重載
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;//用于計數
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;
};
因為函數的聲明和定義全部放在類中,會被編譯器當成內聯函數處理。所以可以根據自身需要,將部分調用不頻繁、稍長的函數的聲明寫在類中,而定義寫在類外。
原文鏈接:https://blog.csdn.net/gfdxx/article/details/127235127
相關推薦
- 2022-10-05 Flutter列表滾動定位超強輔助庫使用示例詳解_IOS
- 2022-06-16 Go基礎教程系列之數據類型詳細說明_Golang
- 2023-07-31 elementui表單密碼強度自定義驗證
- 2022-06-09 Redis超詳細講解高可用主從復制基礎與哨兵模式方案_Redis
- 2022-07-30 Linux文件管理命令行
- 2022-12-04 C++?Boost?Graph算法超詳細精講_C 語言
- 2022-07-30 jQuery?UI工具提示框部件Tooltip?Widget_jquery
- 2022-09-09 OpenSSL生成v3證書方法及配置文件詳解_其它綜合
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支