天天看點

c++---模拟實作日期類

在學習了類和對象的之後大多數都含有一個疑惑,為什麼要學習我們的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;
}
           

會得到結果

c++---模拟實作日期類