前言:在完成c++入门基础及类和对象初步了解,旨在通过此项目完成类和对象相关操作的实践
一,完成准备工作
与之前类似,建立Date.h Date.cpp Test.cpp三个文件
Date.h
完成类及类函数的声明
Date.cpp
完成具体函数的实现
Test.cpp
测试程序可执行性
二, 具体函数的实现
1,构造函数Date(int year = 1900, int month = 1, int day = 1);
Date::Date(int year, int month, int day) { _year = year; _month = month; _day = day; }
可以检查日期准确性
if (!CheckDate()) { cout << "⽇期⾮法" << endl; }
总代码
Date::Date(int year, int month, int day) { _year = year; _month = month; _day = day; if (!CheckDate()) { cout << "⽇期⾮法" << endl; } }
2,void Print();
void Date::Print() { cout << _year << "-" << _month << "-" << _day << endl; }
3,GetMonthDay(int year, int month);
//默认为内联函数incline //频繁调用的简短内敛函数不用建立栈帧 int GetMonthDay(int year, int month) { static int monthDayArray[13] = { -1, 31, 28, 31, 30, 31, 30 ,31, 31, 30, 31, 30, 31 }; //判断闰年 //能被4整除,但不能被100整除 //能被400整除 if (month == 2 && (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) { return 29; } return monthDayArray[month]; }
assert(month > 0 && month < 13);
int GetMonthDay(int year, int month) { assert(month > 0 && month < 13); static int monthDayArray[13] = { -1, 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 monthDayArray[month]; }
注:该函数建立在类里面,因为类里面默认为内联函数incline,频繁调用的简短内敛函数不用建立栈帧
month == 2 在 (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)
因为这样减少判断,极高效率
4,Date& operator+=(int day);
思路:先加上天数与当月总天数比较,比总天数大则减去 当月总天数 月份加一
单独考虑12月变为1月
Date& Date::operator+=(int day) { _day += day; while (_day > GetMonthDay(_year, _month)) { _day -= GetMonthDay(_year, _month); ++_month; if (_month == 13) { _year++; _month = 1; } } return *this; }
//第一种 Date d2 = d1 + 100; //第二种 Date d3(d1 + 100);
注:需考虑day为负数
if (day < 0) { return *this -= (-day); }
总代码
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; }
5,Date operator+(int day) ;
第一种
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; }
d1 += 100; d1.Print();
第二种(复用)
Date Date::operator+(int day) { Date tmp = *this; tmp += day; return tmp; }
注:4和5注意引用的使用
6,Date& operator-=(int day);
思路:先减天数,如果差<0 则月减一(一月变十二月单独考虑 年也要减一)差加上此时月总天数
第一种
Date& Date::operator-=(int day) { _day -= day; while (_day <= 0) { --_month; if (_month == 1) { _month = 12; --_year; } _day += GetMonthDay(_year, _month); } return *this; }
第二种(复用)
Date& Date::operator-=(int day) { *this = *this - day; return *this; }
注:需考虑day为负数
if (day < 0) { return *this += (-day); }
总代码
Date& Date::operator-=(int day) { if (day < 0) { return *this += (-day); } _day -= day; while (_day <= 0) { --_month; if (_month == 1) { _month = 12; --_year; } _day += GetMonthDay(_year, _month); } return *this; }
7,Date operator-(int day);
第一种(复用)
Date Date::operator-(int day) { Date tmp = *this; tmp -= day; return tmp; }
第二种
Date Date::operator-(int day) { Date tmp = *this; tmp._day -= day; while (tmp._day <= 0) { --tmp._month; if (tmp._month == 1) { tmp._month = 12; --tmp._year; } tmp._day += GetMonthDay(tmp._year, tmp._month); } return tmp; }
思考: -复用-= 和 -=复用- 哪个好
结论:-复用-= 更优
原因:
实现 - tmp都需要两次拷贝,效果一样的
-=复用- 也需要拷贝(多了三次拷贝)
8,bool operator<(const Date& d);
bool Date::operator+(const Date& d) { if (_year < d._year) { return true; } else if (_year == d._year) if (_month < d._month) { return true; } else if (_month == d._month) { return _day < d._day; } return false; }
9,bool operator==(const Date& d);
bool Date::operator==(const Date& d) { return _year == d._year && _month == d._month && _day == d._day; }
利用8和9 可以完成其他比较函数
10,bool operator<=(const Date& d);
bool Date::operator<=(const Date& d) { return *this < d || *this == d; }
11,bool operator>(const Date& d);
bool Date::operator>(const Date& d) { return !(*this <= d); }
12,bool operator>=(const Date& d);
bool Date::operator>=(const Date& d) { return !(*this < d); }
13,bool operator!=(const Date& d);
bool Date::operator!=(const Date& d) { return !(*this == d); }
14, Date& operator++();
前置
重载++运算符时,有前置++和后置++,运算符重载函数名都是operator++,⽆法很好的区分。C++规定,后置++重载时,增加⼀个int形参,跟前置++构成函数重载,⽅便区分。
Date& Date::operator++() { *this += 1; return *this; }
15,Date operator++(int);
后置 (比前置多了拷贝,更推荐前置++)
Date Date::operator++(int) { Date tmp(*this); *this += 1; return tmp; }
16,Date& operator--();
Date& Date::operator--() { *this -= 1; return *this; }
17,Date operator--(int);
Date Date::operator--(int) { Date tmp = *this; *this -= 1; return tmp; }
18,int operator-(const Date& d);
日期-日期=天数
方法论:判断大小,小循环+1到与大相同,此时加的次数即为天数
int Date::operator-(const Date& d) { Date max = *this; Date min = d; int flag = 1; if (*this < d) { max = d; min = *this; flag = -1; } int n = 0; while (min != max) { ++min; ++n; } return n* flag; }
19,bool CheckDate();
bool Date::CheckDate() { if (_month < 1 || _month > 12 || _day < 1 || _day > GetMonthDay(_year, _month)) { return false; } else { return true; } }
20,ostream& operator<<(ostream& out, const Date& d);
ostream& operator<<(ostream& out, const Date& d) { out << d._year << "年" << d._month << "⽉" << d._day << "⽇" << endl; return out; }
21,istream& operator>>(istream& in, Date& d);
istream& operator>>(istream& in, Date& d) { cout << "请依次输⼊年⽉⽇:>"; in >> d._year >> d._month >> d._day; if (!d.CheckDate()) { cout << "⽇期⾮法" << endl; } return in; }
重载<<和>>时,需要重载为全局函数,因为重载为成员函数,this指针默认抢占了第⼀个形参位置,第⼀个形参位置是左侧运算对象,调⽤时就变成了 对象<<cout,不符合使⽤习惯和可读性。重载为全局函数把ostream/istream放到第⼀个形参位置就可以了,第⼆个形参位置当类类型对象。
20,21为全局函数
可以用 友元函数声明 来访问类的数据
需要连续输出,流插入为从左向右,故返回值应为 out
// 友元函数声明 friend ostream& operator<<(ostream& out, const Date& d); friend istream& operator>>(istream& in, Date& d);
22,变为const成员函数
在不改变对象的前提下,建议写成const成员函数
三,总代码预览
Date.h
#pragma once #include<iostream> using namespace std; #include<assert.h> class Date { // 友元函数声明 friend ostream& operator<<(ostream& out, const Date& d); friend istream& operator>>(istream& in, Date& d); public: Date(int year = 1900, int month = 1, int day = 1); void Print() const; //默认为内联函数incline //频繁调用的简短内敛函数不用建立栈帧 int GetMonthDay(int year, int month) const { assert(month > 0 && month < 13); static int monthDayArray[13] = { -1, 31, 28, 31, 30, 31, 30 ,31, 31, 30, 31, 30, 31 }; //判断闰年 //能被4整除,但不能被100整除 //能被400整除 if (month == 2 && (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) { return 29; } return monthDayArray[month]; } bool CheckDate() 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; bool operator!=(const Date& d) const; // d1 += 天数 Date& operator+=(int day); Date operator+(int day) const; // d1 -= 天数 Date& operator-=(int day); Date operator-(int day)const; Date& operator++(); Date operator++(int); Date& operator--(); Date operator--(int); int operator-(const Date& d) const; private: int _year; int _month; int _day; }; // 重载 ostream& operator<<(ostream& out, const Date& d); istream& operator>>(istream& in, Date& d);
Date.cpp
#include"Date.h" Date::Date(int year, int month, int day) { _year = year; _month = month; _day = day; if (!CheckDate()) { cout << "⽇期⾮法" << endl; } } void Date::Print() const { cout << _year << "-" << _month << "-" << _day << endl; } 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) const { Date tmp = *this; tmp += day; /*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 == 1) { _month = 12; --_year; } _day += GetMonthDay(_year, _month); } return *this; } //第二种 //Date& Date::operator-=(int day) //{ // *this = *this - day; // return *this; //} Date Date::operator-(int day) const { Date tmp = *this; tmp -= day; //tmp._day -= day; //while (tmp._day <= 0) //{ // --tmp._month; // if (tmp._month == 1) // { // tmp._month = 12; // --tmp._year; // } // tmp._day += GetMonthDay(tmp._year, tmp._month); //} // return tmp; } bool Date::operator<(const Date& d) const { if (_year < d._year) { return true; } else if (_year == d._year) if (_month < d._month) { return true; } else if (_month == d._month) { return _day < d._day; } return false; } bool Date::operator==(const Date& d) const { return _year == d._year && _month == d._month && _day == d._day; } 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); } bool Date::operator!=(const Date& d) const { return !(*this == d); } Date& Date::operator++() { *this += 1; return *this; } 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; } int Date::operator-(const Date& d) const { Date max = *this; Date min = d; int flag = 1; if (*this < d) { max = d; min = *this; flag = -1; } int n = 0; while (min != max) { ++min; ++n; } return n* flag; } bool Date::CheckDate() const { if (_month < 1 || _month > 12 || _day < 1 || _day > GetMonthDay(_year, _month)) { return false; } else { return true; } } ostream& operator<<(ostream& out, const Date& d) { out << d._year << "年" << d._month << "⽉" << d._day << "⽇" << endl; return out; } istream& operator>>(istream& in, Date& d) { cout << "请依次输⼊年⽉⽇:>"; in >> d._year >> d._month >> d._day; if (!d.CheckDate()) { cout << "⽇期⾮法" << endl; } return in; }