在學習了類和對象的之後大多數都含有一個疑惑,為什麼要學習我們的class ?因為類封裝了我們的屬性和方法,不隻是在我們寫的時候更加具有我們的可讀性,也會讓代碼更加具有通路控制的限制。
實作日期類,為什麼要實作日期類,因為日期在我們的生活中随處可見,實作一個日期類隻在使用的時候調用類以及類中的方法就好了,另一個原因是在常見的類型,比如數字等等都具有±*/等等的方法,但是日期類是我們自定義的類型,又怎樣去實作日期類的加減呢?
運算符重載就能解決我們的問題,運算符重載時類為了解決自定義類型的運算,比如在一個類定義了之後會預設的生成一個指派運算符的重載,
運算符重載關鍵字operator+需要重載的運算符
我們下面使用通過我們運算符的重載來實作我們的日期類
首先在類中需要含有三個我們的私有成員_day,_month,_year
- 構造函數和析構函數,以及拷貝構造,指派操作符都可以不用實作,因為我們這裡不涉及深拷貝淺拷貝,不會造成一個記憶體多次釋放的情況,使用編譯器預設生成的就可以滿足需求
- 時間比較運算符的重載
bool operator>(const Date& d) const;
bool operator>=(const Date& d) const;
bool operator<(const Date& d) const;
bool operator<=(const Date& d) const;
bool operator==(const Date& d) const;
bool operator!=(const Date& d) const;
- +=、+、-、-=運算符重載
Date operator-(int day) const;
Date& operator-=(int day);
Date& operator+=(int day);//
Date operator+(int day) const;//+天數
-
++,–
這裡++,–都會出現前置++和後置++,–同樣也會出現,在這裡我們為了區分使用一個占位符來區分前置和後置,在後置中加上int參數來占位
Date& operator++(); // 前置++
Date operator++(int); // 後置++
Date& operator--(); // 前置--
Date operator--(int); //後置--
-
“ -” 運算符
這裡和上面的不一樣上面是減去一個天數,這裡是Date-Date(兩個類進行相減)。
可以說Date類麻雀雖小,但是五髒俱全,不僅僅對我們的類的構造函數,析構函數等等都有一定的領悟,同時包含運算符的重載。以及在代碼中含有const和&。是以此類是我們需要學習的第一個class類
下面是代碼,我會在代碼中詳細的進行注釋友善學習
Date.h
#pragma once
#include <iostream>
#include <assert.h>
using std::cout;
using std::endl;
class Date{
public:
//得到一年的天數
int getDays(int year) const {
if (((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))){
return 366;
}
return 365;
}
//得到某年某月的天數,這裡需要注意的是閏年的判斷
inline int GetMonthDay(int year, int month) const{
static int monthArray[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;
}
return monthArray[month];
}
//得到從現在打1900 1 1的天數,這裡是為了友善計算日期-日期
int GetDaysTo199011(Date d)const{
int ret1 = 0;
int i = 0;
for (i = 1900; i < d._year; i++){
ret1 += Date::getDays(i);
}
for (int j = 1; j < d._month; j++){
ret1 += GetMonthDay(i, j);
}
ret1 += d._day - 1;
return ret1;
}
//構造函數,是預設的構造函數,使用了全預設的參數
Date(int year=1900, int month=1, int day=1){
if (year >= 1900
&& month > 0 && month < 13
&& day > 0 && day <= GetMonthDay(year, month)){
_year = year;
_month = month;
_day = day;
}
else{
//assert(false);
cout << "非法日期" << endl;
}
}
void Print(){
cout << _year << "-" << _month << "-" << _day << endl;
}
//運算符的重載,這裡加上const是因為比較的時候我們不會改變我們的Date值,&傳遞是因為減少一個拷貝構造
bool operator>(const Date& d) const;
bool operator>=(const Date& d) const;
bool operator<(const Date& d) const;
bool operator<=(const Date& d) const;
bool operator==(const Date& d) const;
bool operator!=(const Date& d) const;
//前置++和後置++是用占位符進行區分
Date& operator++(); // 前置++
Date operator++(int); // 後置++
Date& operator+=(int day);
//這裡的const是const成員函數,是修飾this指針的,是this指針不能被修改
Date operator+(int day) const;//+天數
Date& operator--(); // 前置--
Date operator--(int); // 後置--
Date operator-(int day) const;
Date& operator-=(int day);
int operator-(const Date&d) const;
private:
int _year;
int _month;
int _day;
};
在實作類中的方法的時候需要注意的是我們需要代碼複用,不用每一個函數都自己去實作,可以依靠我們實作過的代碼去實作其他的函數,比如比較運算符我們就可以訓示線兩個,例如實作了>和==。那麼<=就是!>,其他都是類似。保持一個原則,盡量減少拷貝構造和代碼的備援。
Date.cpp
#include "Date.h"
Date& Date::operator++(){//前置++
return *this += 1;
}
Date Date::operator++(int){//後置++
Date ret = *this;//這是一個拷貝構造
*this += 1;
return ret;
}
Date Date::operator+(int day) const{//調用—>+=來計算
Date ret = *this;
ret += day;
return ret;
}
Date& Date::operator+=(int day){
if (day<0){
day = -day;
return *this -= day;
}
_day += day;
while (_day > GetMonthDay(_year, _month)){
_day -= GetMonthDay(_year, _month);
_month++;
if (_month == 13){
_month = 1;
_year++;
}
}
return *this;
}
Date& Date::operator-=(int day){ //-=
if (day < 0){
day = 0 -day;
return *this += day;
}
this->_day -= day;
while (_day <= 0){
_month--;
if (_month == 0){
_month = 12;
_year--;
}
_day = _day + GetMonthDay(_year, _month);
}
return *this;
}
Date Date::operator-(int day) const {//-day
Date ret = *this;
ret -= day;
return ret;
}
Date& Date::operator--(){
return *this-= 1;
}
Date Date::operator--(int){
Date ret = *this;
*this -= 1;
return ret;
}
bool Date::operator==(const Date& d) const{
return (this->_year == d._year
&& this->_month == d._month
&&this->_day == d._day);
}
bool Date::operator<(const Date& d)const {
if (this->_year < d._year){
return true;
}
if (this->_year == d._year && this->_month < d._month){
return true;
}
if (this->_year == d._year&&this->_month == d._month&&this->_day < d._day){
return true;
}
return false;
}
bool Date::operator!=(const Date& d)const{
return !(*this == d);
}
bool Date::operator<=(const Date& d)const{
return ((*this < d) || (*this == d));
}
bool Date::operator>(const Date& d)const{
return !(*this <= d);
}
bool Date::operator>=(const Date& d)const{
return !(*this < d);
}
//計算兩個日期的減法
int Date::operator-(const Date&d) const{
//計算一個日期到另一個日期相聚的天數
return GetDaysTo199011(*this) - GetDaysTo199011(d);
}
建立main.cpp進行測試
main.cpp
#include "Date.h"
void test(){
cout << "測試+= + 前置++ 後置++" << endl;
Date d1(2012, 2, 5);
Date d2(2036, 5, 6);
(d1 + 10).Print();//測試+
d2 += 20;//測試+=
d2.Print();
d2++.Print();//測試後置++
(++d2).Print();//測試前置++
cout << "測試-= - 前置-- 後置--" << endl;
//測試-=
Date d3(2018, 1, 1);
cout << "aaaaa" << endl;
d3 -= 1;
d3.Print();
//測試前置--和後置--和-
Date d4 = d3 - 3;
d4.Print();
(--d4).Print();
(d4--).Print();
Date d5(2015, 1, 31);
Date d6(2015, 2,1 );
cout << "測試關系運算符" << endl;
cout << "小于:"<<(d5 < d6) << endl;
cout << "等于:"<<(d5 == d6) << endl;
cout << (d5 - d6) << endl;
}
int main(){
test();
system("pause");
return EXIT_SUCCESS;
}
會得到結果