C++實現(xiàn)日期類
├─屬性:
│ ├─年份
│ ├─月份
│ └─日期
├─方法:
│ ├─構(gòu)造函數(shù)
│ ├─拷貝構(gòu)造函數(shù)
│ ├─析構(gòu)函數(shù)
│ ├─設(shè)置年份
│ ├─設(shè)置月份
│ ├─設(shè)置日期
│ ├─獲取年份
│ ├─獲取月份
│ ├─獲取日期
│ ├─判斷是否為閏年
│ ├─計算該日期是該年的第幾天
│ ├─計算該日期是星期幾
│ └─重載運算符(+、-、==、!=、<、>、<=、>=)
一、??頭文件的聲明(Date.h)
??日期類的實現(xiàn),將按以下聲明依次進行,其中因為Print函數(shù)比較短,直接放到類里面讓其變成內(nèi)聯(lián)函數(shù)
#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
class Date
{
public:
Date(int year = 1, int month = 1, int day = 1);
void Print();
int GetMonthDay(int year, int month);
bool operator==(const Date& y);
bool operator!=(const Date& y);
bool operator>(const Date& y);
bool operator<(const Date& y);
bool operator>=(const Date& y);
bool operator<=(const Date& y);
int operator-(const Date& d);
Date& operator+=(int day);
Date operator+(int day);
Date& operator-=(int day);
Date operator-(int day);
Date& operator++();
Date operator++(int);
Date& operator--();
Date operator--(int);
private:
int _year;
int _month;
int _day;
};
class Date
{
public:
// 獲取某年某月的天數(shù)
int GetMonthDay(int year, int month)
{
static int days[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30,
31};
int day = days[month];
if (month == 2
&&((year % 4 == 0 && year % 100 != 0) || (year%400 == 0)))
{
day += 1;
}
return day;
}
// 全缺省的構(gòu)造函數(shù)
Date(int year = 1900, int month = 1, int day = 1);
// 拷貝構(gòu)造函數(shù)
// d2(d1)
Date(const Date& d);
// 賦值運算符重載
// d2 = d3 -> d2.operator=(&d2, d3)
Date& operator=(const Date& d);
// 析構(gòu)函數(shù)
~Date();
// 日期+=天數(shù)
Date& operator+=(int day);
// 日期+天數(shù)
Date operator+(int day);
// 日期-天數(shù)
Date operator-(int day);
// 日期-=天數(shù)
Date& operator-=(int day);
// 前置++
Date& operator++();
// 后置++
Date operator++(int);
// 后置--
Date operator--(int);
// 前置--
Date& operator--();
// >運算符重載
bool operator>(const Date& d);
// ==運算符重載
bool operator==(const Date& d);
// >=運算符重載
bool operator >= (const Date& d);
// <運算符重載
bool operator < (const Date& d);
// <=運算符重載
bool operator <= (const Date& d);
// !=運算符重載
bool operator != (const Date& d);
// 日期-日期 返回天數(shù)
int operator-(const Date& d);
private:
int _year;
int _month;
int _day;
};
二、??獲取天數(shù)的函數(shù)
??而我們實現(xiàn)日期類經(jīng)常要用到某月有多少天,在這里先把獲得某月有多少天的函數(shù)實現(xiàn)出來。實現(xiàn)時先檢查傳參有沒有問題,在注意把數(shù)組設(shè)置成靜態(tài)的,出了作用域還能訪問,就不需要考慮每次調(diào)用函數(shù)建立棧幀后重新給數(shù)組分配空間的事情了,因為數(shù)組一直被存放在靜態(tài)區(qū) 其次我們先判斷這個月是不是二月份,避免判斷某年是平年還是閏年一大堆操作后,發(fā)現(xiàn)月份不是二月份
int Date::GetMonthDay(int year, int month)
{
assert(year >= 1 && month >= 1 && month <= 12);
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];
}
三、??Date的默認(rèn)成員函數(shù)
??1.編譯器默認(rèn)生成的構(gòu)造函數(shù)不會處理內(nèi)置類型,所以我們需要自己去寫構(gòu)造函數(shù),推薦全缺省的構(gòu)造函數(shù),編譯器對自定義類型會自動調(diào)用該類型的默認(rèn)構(gòu)造
??2.由于Date類的成員變量都是內(nèi)置類型,所以析構(gòu)函數(shù)不需要我們自己寫,因為沒有資源的申請。并且拷貝構(gòu)造和賦值重載也不需要寫,因為Date類不涉及深拷貝的問題,僅僅使用淺拷貝就夠了
Date::Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
if (_year < 1 ||
_month < 1 || _month > 12 ||
_day < 1 || _day > GetMonthDay(_year, _month))
{
//assert(false);
Print();
cout << "日期非法" << endl;
}
}
??用一個類初始化另外一個類
Date::Date(const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
四、??日期類的大小比較
??由于日期類的大小比較,均不涉及對自身的改變,對此,我們統(tǒng)一用const來修飾this指針,讓其變成const成員函數(shù),減少代碼的出錯性
五、??>運算符重載
??在這里我們找出所有日期a大于日期b的情況 第一種:年比年大 第二種:年相同 月比月大 第三種:年和月都相同 日比日大 再依次向下寫就完成了>的比較
bool Date::operator>(const Date& y)
{
if (_year > y._year)
{
return true;
}
else if (_year == y._year && _month > y._month)
{
return true;
}
else if (_year == y._year && _month == y._month && _day > y._day)
{
return true;
}
return false;
}
六、??==運算符重載
bool Date::operator==(const Date& y)
{
return _year == y._year
&& _month == y._month
&& _day == y._day;
}
七、??>= < <= !=對> ==的復(fù)用
// d1 != d2
bool Date::operator!=(const Date& y)
{
return !(*this == y);
}
bool Date::operator>(const Date& y)
{
if (_year > y._year)
{
return true;
}
else if (_year == y._year && _month > y._month)
{
return true;
}
else if (_year == y._year && _month == y._month && _day > y._day)
{
return true;
}
return false;
}
bool Date::operator>=(const Date& y)
{
return *this > y || *this == y;
}
bool Date::operator<(const Date& y)
{
return !(*this >= y);
}
bool Date::operator<=(const Date& y)
{
return !(*this > y);
}
八、??日期類的計算
??日期類的連續(xù)賦值
在內(nèi)置類型的適合我們經(jīng)常有連續(xù)賦值的習(xí)慣,類似a1=a2=a3這種,而日期類也支持連續(xù)賦值的操作對此我們返回值不能寫void 而應(yīng)該返回引用,我們可以減少拷貝,從而提高效率 這是一名C/C++程序員的基本素養(yǎng)
Date& Date::operator=(const Date& d)
{
this->_year = d._year;
this->_month = d._month;
this->_day = d._day;
return *this;
}
??日期類的加法
+=運算符重載和+對+=的復(fù)用
??+=實現(xiàn)的思路就是,實現(xiàn)一個循環(huán),直到天數(shù)回到該月的正常天數(shù)為止,在循環(huán)內(nèi)部要做的就是進月和進年,讓天數(shù)不斷減去本月天數(shù),直到恢復(fù)本月正常天數(shù)時,循環(huán)結(jié)束,返回對象本身即可
// d1 += 100
Date& Date::operator+=(int day)
{
if (day < 0)
{
return *this -= (-day);
}
_day += day;
while (_day > GetMonthDay(_year, _month))
{
_day -= GetMonthDay(_year, _month);
++_month;
if (_month == 13)
{
_year++;
_month = 1;
}
}
return *this;
}
Date Date::operator+(int day)
{
Date tmp(*this);
tmp += day;
return tmp;
}
??-=實現(xiàn)的思路就是,實現(xiàn)一個循環(huán),直到天數(shù)變?yōu)檎龜?shù)為止,在循環(huán)內(nèi)部要做的就是借月和借年,讓天數(shù)不斷加上上一個月份的天數(shù),直到恢復(fù)正數(shù)為止,循環(huán)結(jié)束,返回對象本身
Date& Date::operator-=(int day)
{
if (day < 0)
{
return *this += (-day);
}
_day -= day;
while (_day <= 0)
{
--_month;
if (_month == 0)
{
--_year;
_month = 12;
}
_day += GetMonthDay(_year, _month);
}
return *this;
}
Date Date::operator-(int day)
{
Date tmp(*this);
tmp -= day;
return tmp;
}
??前置++和后置++重載
后置++比前置++多一個參數(shù)int 同時后置返回的臨時變量 不能添加引用 同時兩個this都被改變了 不加const修飾
++d1;
d1.operator++();
d1.Print();
d1++;
d1.operator++(10);
d1.operator++(1);
d1.Print();
// ++d1
Date& Date::operator++()
{
*this += 1;
return *this;
}
// d1++
Date Date::operator++(int)
{
Date tmp(*this);
*this += 1;
return tmp;
}
??前置??和后置??重載文章來源:http://www.zghlxwxcb.cn/news/detail-718313.html
Date& Date::operator--()
{
*this -= 1;
return *this;
}
Date Date::operator--(int)
{
Date tmp(*this);
*this -= 1;
return tmp;
}
九、??日期?日期重載
??日期類相減不需要日期本身,因此用const修飾。由于采用運算法求日期減去日期比較麻煩 還好考慮差有幾年 幾月 甚至幾月中是否包括二月 所以在這樣我們采用小日期自增的方式實現(xiàn) 用一個變量n記錄文章來源地址http://www.zghlxwxcb.cn/news/detail-718313.html
// d1 - d2
int Date::operator-(const Date& d)
{
// 假設(shè)左大右小
int flag = 1;
Date max = *this;
Date min = d;
// 假設(shè)錯了,左小右大
if (*this < d)
{
max = d;
min = *this;
flag = -1;
}
int n = 0;
while (min != max)
{
++min;
++n;
}
return n * flag;
}
十、??日期類實現(xiàn)總代碼
#include "Date.h"
Date::Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
if (_year < 1 ||
_month < 1 || _month > 12 ||
_day < 1 || _day > GetMonthDay(_year, _month))
{
//assert(false);
Print();
cout << "日期非法" << endl;
}
}
void Date::Print()
{
cout << _year << "/" << _month << "/" << _day << endl;
}
bool Date::operator==(const Date& y)
{
return _year == y._year
&& _month == y._month
&& _day == y._day;
}
// d1 != d2
bool Date::operator!=(const Date& y)
{
return !(*this == y);
}
bool Date::operator>(const Date& y)
{
if (_year > y._year)
{
return true;
}
else if (_year == y._year && _month > y._month)
{
return true;
}
else if (_year == y._year && _month == y._month && _day > y._day)
{
return true;
}
return false;
}
bool Date::operator>=(const Date& y)
{
return *this > y || *this == y;
}
bool Date::operator<(const Date& y)
{
return !(*this >= y);
}
bool Date::operator<=(const Date& y)
{
return !(*this > y);
}
int Date::GetMonthDay(int year, int month)
{
assert(year >= 1 && month >= 1 && month <= 12);
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];
}
// d1 += 100
Date& Date::operator+=(int day)
{
if (day < 0)
{
return *this -= (-day);
}
_day += day;
while (_day > GetMonthDay(_year, _month))
{
_day -= GetMonthDay(_year, _month);
++_month;
if (_month == 13)
{
_year++;
_month = 1;
}
}
return *this;
}
Date Date::operator+(int day)
{
Date tmp(*this);
tmp += day;
return tmp;
}
//
// d1 += 100
//Date& Date::operator+=(int day)
//{
// //Date d = *this + day;
// //*this = d;
//
// *this = *this + day;
// return *this;
//}
//
//Date Date::operator+(int day)
//{
// Date tmp(*this);
//
// tmp._day += day;
// while (tmp._day > GetMonthDay(tmp._year, tmp._month))
// {
// tmp._day -= GetMonthDay(tmp._year, tmp._month);
//
// ++tmp._month;
//
// if (tmp._month == 13)
// {
// tmp._year++;
// tmp._month = 1;
// }
// }
//
// return tmp;
//}
Date& Date::operator-=(int day)
{
if (day < 0)
{
return *this += (-day);
}
_day -= day;
while (_day <= 0)
{
--_month;
if (_month == 0)
{
--_year;
_month = 12;
}
_day += GetMonthDay(_year, _month);
}
return *this;
}
Date Date::operator-(int day)
{
Date tmp(*this);
tmp -= day;
return tmp;
}
// 21:13繼續(xù)
// ++d1
Date& Date::operator++()
{
*this += 1;
return *this;
}
// d1++
Date Date::operator++(int)
{
Date tmp(*this);
*this += 1;
return tmp;
}
Date& Date::operator--()
{
*this -= 1;
return *this;
}
Date Date::operator--(int)
{
Date tmp(*this);
*this -= 1;
return tmp;
}
// d1 - d2
int Date::operator-(const Date& d)
{
// 假設(shè)左大右小
int flag = 1;
Date max = *this;
Date min = d;
// 假設(shè)錯了,左小右大
if (*this < d)
{
max = d;
min = *this;
flag = -1;
}
int n = 0;
while (min != max)
{
++min;
++n;
}
return n * flag;
}
#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
class Date
{
public:
Date(int year = 1, int month = 1, int day = 1);
void Print();
int GetMonthDay(int year, int month);
bool operator==(const Date& y);
bool operator!=(const Date& y);
bool operator>(const Date& y);
bool operator<(const Date& y);
bool operator>=(const Date& y);
bool operator<=(const Date& y);
int operator-(const Date& d);
Date& operator+=(int day);
Date operator+(int day);
Date& operator-=(int day);
Date operator-(int day);
Date& operator++();
Date operator++(int);
Date& operator--();
Date operator--(int);
private:
int _year;
int _month;
int _day;
};
#include "Date.h"
void TestDate1()
{
Date d1(2023, 10, 24);
d1.Print();
Date ret1 = d1 - 100;
ret1.Print();
Date ret2 = d1 - 10000;
ret2.Print();
Date ret3 = d1 + 100;
ret3.Print();
Date ret4 = d1 + 10000;
ret4.Print();
}
void TestDate2()
{
Date d1(2023, 10, 24);
d1.Print();
// 語法設(shè)計,無法邏輯閉環(huán),那么這時就只能特殊處理
// 特殊處理
++d1;
d1.operator++();
d1.Print();
d1++;
d1.operator++(10);
d1.operator++(1);
d1.Print();
}
void TestDate3()
{
Date d1(2023, 10, 24);
d1.Print();
Date d2(2024, 5, 5);
d2.Print();
Date d3(2024, 8, 1);
d3.Print();
cout << d2 - d1 << endl;
cout << d1 - d3 << endl;
}
void TestDate4()
{
Date d1(2023, 10, 24);
d1 += -100;
d1.Print();
}
int main()
{
TestDate4();
return 0;
}
到了這里,關(guān)于【C++】:拷貝構(gòu)造函數(shù)與賦值運算符重載的實例應(yīng)用之日期類的實現(xiàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!