在学习了类和对象的之后大多数都含有一个疑惑,为什么要学习我们的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;
}
会得到结果