dede 电商网站,计算机编程培训班,南昌网站seo技术,哈尔滨有哪些做网站的公司♥♥♥~~~~~~欢迎光临知星小度博客空间~~~~~~♥♥♥ ♥♥♥零星地变得优秀~也能拼凑出星河~♥♥♥ ♥♥♥我们一起努力成为更好的自己~♥♥♥ ♥♥♥如果这一篇博客对你有帮助~别忘了点赞分享哦~♥♥♥ ♥♥♥如果有什么问题可以评论区留言或者私信我哦~♥♥♥ ✨✨✨✨✨✨ 个… ♥♥♥~~~~~~欢迎光临知星小度博客空间~~~~~~♥♥♥ ♥♥♥零星地变得优秀~也能拼凑出星河~♥♥♥ ♥♥♥我们一起努力成为更好的自己~♥♥♥ ♥♥♥如果这一篇博客对你有帮助~别忘了点赞分享哦~♥♥♥ ♥♥♥如果有什么问题可以评论区留言或者私信我哦~♥♥♥ ✨✨✨✨✨✨ 个人主页✨✨✨✨✨✨ ❤C专栏中比较重要的类与对象知识现在已经更新完毕❤欢迎大家随时访问哦❤ 类与对象——第一集 类与对象——第二集 类与对象——第三集 类与对象——第四集类与对象——最后一集日期类的实现 在前面的博客内容中我们已经学习了C中类与对象的大部分知识这一篇博客我们将会利用前面学习到的知识来实现一个日期类~用实践检验我们学习的成果~准备好了吗~我们发车啦~
目录
实现一个怎么样的日期类
定义一个日期类
构造函数
拷贝构造函数
打印日期
使用成员函数
流插入运算符重载
流提取运算符重载
赋值运算符重载
判断日期大小关系
等于
不等于
大于
大于等于
小于
小于等于
日期天数
日期天数
日期-天数
日期-天数
前置
后置
前置--
后置--
日期-日期
总代码
Date.h
Date.cpp 实现一个怎么样的日期类
我们生活中经常会使用到日期比如日期加天数日期-日期倒计时等等这里我们要实现的日期类就是来实现这样一些具有实际意义的日期处理~像日期加日期这种是没有实际意义的我们这里也就不会进行实现~
这里我们创建三个文件~ Date.h 定义日期类结构对要提供的操作进行声明 Date.cpp 具体实现各种操作 test.cpp 进行各种操作的测试 定义一个日期类
我们这里实现的日期类是包含年、月、日的所以我们给到的成员变量就有年、月、日同时使用private访问限定符进行修饰不希望只希望在这一个类里面访问成员变量~
#includeiostream
using namespace std;
//定义日期类
class Date
{
private://成员变量 年、月、日int _year;int _month;int _day;//前面加一个下划线便于区分
public://成员函数};//不要忘记末尾的分号其他文件就可以包含我们自己写的头文件 注意这里是我们自己写的头文件所以包含头文件的时候应该是双引号 而不是尖括号 构造函数
我们不希望使用编译器生成的构造函数让日期是随机值所以我们这里需要自己写构造函数~
同时在构造的同时我们也可以检查日期是否合法~
//检查日期是否合法~
bool Date::CheckDate()const
{if (_month 12 || _month 1 || _day 0 || _day GetMonthDay(_year,_month)){return false;}return true;
}
//Date::Date(int year 0,int month 0,int day 0)//err
Date::Date(int year,int month,int day)//声明和定义不可以同时给缺省参数
//在声明里面给缺省参数
{_year year;_month month;_day day;//检查日期是否合法if (!CheckDate()){cout 日期非法 *this endl;}
}
拷贝构造函数 拷贝构造函数可以用一个已经初始化的对象来初始化新创建的对象事实上这里没有涉及到资源管理我们可以不显示写拷贝构造函数直接使用编译器自动生成的拷贝构造函数也是没有问题的~ 显示写拷贝构造函数
//拷贝构造函数——可以用来初始化新创建的对象
Date::Date(const Date d)
{_year d._year;_month d._month;_day d._day;
}补充自定义类型传值传参和传值返回会产生临时对象所以它们都会调用拷贝构造函数~ C规定自定义类型对象进行拷贝的行为必须调用拷贝构造 打印日期
接下来我们先来一个简单的也是我们以前练习过的打印日期~
我们给出两种方法一个是成员函数一个是流插入运算符重载~
使用成员函数 使用成员函数的好处是每一个成员函数参数都隐含一个this指针这样我们就可以直接获得当前对象年月日进行打印~ void Date::Print()const
//const 修饰this指针指向的内容我们不希望内容被修改
{cout _year 年 _month 月 _day 日 endl;
}
流插入运算符重载 》 流插入运算符有两个操作数在这里一个是ostream类型一个是Date类型如果把它设计成成员函数那么隐含的this指针在第一个参数就不符合我们平常使用的习惯~所以我们可以把它设计为全局函数~ 》但是全局函数又不可以访问类的私有成员了前面我们提到过三种解决方案~~ 1.使用友元函数 2.提供get成员函数获取年月日 3.将年月日成员变量改为公有 这里我们使用友元函数来达到目的~ 在类里面加上friend关键字说明这个函数是这个类的友元函数可以访问私有成员~ 类外面对这个友元函数进行声明这个时候就不需要再加friend关键字了 在Date.cpp文件里面进行函数的定义~
ostream operator (ostream ou, const Date d)
{ou d._year 年 d._month 月 d._day 日 endl;return ou;//有返回值实现连续输出
} 注意这个重载函数返回值实现我们进行连续输出的操作~同时这里返回值只能使用引用返回~输出流我们是不可以改变的~ 流提取运算符重载
知道了流插入运算符重载流提取运算符重载就十分容易了~ 在类里面加上friend关键字说明这个函数是这个类的友元函数可以访问私有成员~这里与流插入运算符重载不相同的是d不能加const修饰因为我们本身输入是修改了内容的~ 类外面对这个友元函数进行声明这个时候就不需要再加friend关键字了 在Date.cpp文件里面进行函数的定义~这里还可以增加一个小细节就是检查日期是否合法~ istream operator(istream in, Date d)
{while (1){in d._year d._month d._day;//检查日期是否合法if (d.CheckDate()){break;}else{cout 日期非法请重新输入 endl;}}return in;
}
赋值运算符重载 》对于自定义类型使用赋值运算符重载可以让我们完成两个已经初始化对象的拷贝~ 》注意与拷贝构造函数进行区分拷贝构造函数是用一个已经初始化的对象来初始化一个新创建的对象~ 》赋值运算符重载同样有返回值这样就可以实现连续赋值~ // d1 d2
//* this d
//这里需要修改*this
Date Date::operator(const Date d)
{_year d._year;_month d._month;_day d._day;return *this;//有返回值实现连续赋值
}
判断日期大小关系
等于
等于这个很好判断只需要年月日都是相等的那么这两个日期就是相等的~
bool Date::operator(const Date d)const
{//年月日相等就相等return (_year d._year) (_month d._month) (_day d._day);
}
不等于 这里有两个方法 》一个是直接写只要年月日有一个不相同那么这两个日期就不相等~ 》一个是进行代码复用更加推荐这个方式减少代码量这里日期不相等就是相等的否 bool Date::operator!(const Date d)const
{//1.直接写/*return (_year ! d._year)|| (_month ! _month)|| (_day ! d._day);*///2.代码复用return !(*this d);
}大于 判断思路先判断年年大就大年相等判断月月大就大月相等就判断日日大就大 bool Date::operator(const Date d)const
{if (_year d._year){return true;}//年相等判断月if (_year d._year){if (_month d._month){return true;}//月相等判断天else if(_month d._month){if (_day d._day){return true;}}}return false;
}大于等于
这里使用代码复用就大大减少我们的代码量了~事实上前面实现了判断大于和等于接下来的代码判断都可以使用代码复用~
bool Date::operator(const Date d)const
{//代码复用return (*this d) || (*this d);
}小于
bool Date::operator(const Date d)const
{代码复用return !((*this d) || (*this d));
}
小于等于
bool Date::operator(const Date d)const
{//代码复用return (*this d) || (*this d);
}
日期天数 》思路加的天数先加在日上面得到总天数判断总天数是否大于当前月份天数比当前月份天数大就用总天数减去当前月份天数月加加再判断是否大于当前月份天数如此循环~ 》这里我们就需要提供一个获取日期天数的方法这里我们直接把这个函数定义在类里面这个函数就成为了内联函数可以直接在调用的地方进行展开~ 获取月份天数
//获取月份天数
// 直接定义在类里面成为inline函数
int GetMonthDay(int y, int m)const
{static int arr[13] { 0,31,28,31,30,31,30,31,31,30,31, 30,31 };// 0 1 2 3 4 5 6 7 8 9 10 11 12if (m 2 ((y % 400 0) || (y % 4 0 y % 100 ! 0)))//闰年的二月29天{return 29;}return arr[m];
}
日期天数
//使用引用返回减少拷贝次数
Date Date::operator(int day)
{//特殊处理day0调用日期-天数if (day 0)//调用日期减天数{*this - (-day);}else{_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);//特殊处理day 0if (day 0){tmp - (-day);}else{//代码复用tmp day;}return tmp;
}
日期-天数 》思路先让日减去当前月天数如果_day0,就让_month-- 注意特殊处理_month0的时候_year--,_month1),_day加上_month的天数,再次判断_day是不是小于0 Date Date::operator-(int day)
{if (day 0){*this (-day);}else{_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);//特殊处理day 0,调用天数if (day 0){tmp (-day);}else{//代码复用tmp - day;}return tmp;
}
前置 》前置是先再使用事实上也就是当前日期本身1我们一样可以使用代码复用~ Date Date::operator()
{*this 1;return *this;
}
后置 》这里像前面那样为了与前置区分这里参数会有一个int进行区分没有什么特别的意义只是为了好区分~ 》后置是先使用再所有我们需要使用一个临时对象来保存之前的值进行返回~ Date Date::operator(int)//后面加int与前置区分
{Date tmp *this;*this 1;return tmp;
}
接下来的前置--和后置--有了这些基础相信就是小菜一碟了~
前置--
Date Date::operator--()
{*this - 1;//本身-1return *this;
}
后置--
Date Date::operator--(int)
{Date tmp *this;*this - 1;return tmp;
}
日期-日期
日期-日期是一个比较有意义的计算而日期日期没有实际意义这里就不进行实现了~ 》日期-日期我们可以直接让小日期走到大日期进行计数 》同时注意是前面的日期大还是后面的日期大~使用一个flag进行标记~ //*this —— d
int Date::operator-(const Date d)const
{int flag 1;//标记默认前面的日期大Date max *this;Date min d;if (*this d){//后面的日期大重新赋值max d;min *this;flag -1;}int n 0;//计数//让小日期走到大日期进行计数while (min ! max){min;//或者min 1;n;}return n * flag;
}
到这里我们就实现了一个比较完整的日期类~如果小伙伴们有更好的想法~欢迎评论区留言或者私信小编哦❤
总代码
Date.h
#pragma once#includeiostream
using namespace std;
//定义日期类
class Date
{
private://成员变量 年、月、日int _year;int _month;int _day;//前面加一个下划线便于区分
public://成员函数//构造函数Date(int year 0, int month 0, int day 0);//全缺省参数//拷贝构造函数Date(const Date d);//检查日期是否合法bool CheckDate()const;//获取月份天数// 直接定义在类里面成为inline函数int GetMonthDay(int y, int m)const{static int arr[13] { 0,31,28,31,30,31,30,31,31,30,31, 30,31 };// 0 1 2 3 4 5 6 7 8 9 10 11 12if (m 2 ((y % 400 0) || (y % 4 0 y % 100 ! 0)))//闰年的二月29天{return 29;}return arr[m];}//显示日期//1.成员函数//后面加const不希望this指针指向的内容被修改void Print()const;//2.使用友元,流插入运算符重载进行输出//日期d加const不希望内容被修改friend ostream operator (ostream ou, const Date d);//流提取运算符重载//日期d不加const输入本身修改了内容//输入后需要判断日期是否合法friend istream operator(istream in, Date d);//日期操作运算符重载//赋值运算符重载Date operator(const Date d);//日期相等bool operator(const Date d)const;//只是判断不希望日期被修改 *this 和 d//不相等!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);//日期加天数不改变本身Date operator(int day);//日期-天数——改变日期本身Date operator-(int day);//日期-天数不改变本身Date operator-(int day);//前置——先再使用,本身发生变化Date operator();//后置——先使用再Date operator(int);//后面加int与前置区分//前置--Date operator--();//后置--Date operator--(int);//日期减日期int operator-(const Date d)const;};//不要忘记末尾的分号//和定义为全局函数符合我们的使用习惯
//Date的友元函数可以访问Date类里面的私有成员
ostream operator (ostream ou, const Date d);//类外不需要再使用friend关键字istream operator(istream in, Date d);
Date.cpp
#includeDate.h//自己写的头文件使用//Date::Date(int year 0,int month 0,int day 0)//err
Date::Date(int year,int month,int day)//声明和定义不可以同时给缺省参数
//在声明里面给缺省参数
{_year year;_month month;_day day;//检查日期是否合法if (!CheckDate()){cout 日期非法 *this endl;}
}//拷贝构造函数——可以用来初始化新创建的对象
Date::Date(const Date d)
{_year d._year;_month d._month;_day d._day;
}//检查日期是否合法~
bool Date::CheckDate()const
{if (_month 12 || _month 1 || _day 0 || _day GetMonthDay(_year,_month)){return false;}return true;
}void Date::Print()const
//const 修饰this指针指向的内容我们不希望内容被修改
{cout _year 年 _month 月 _day 日 endl;
}ostream operator (ostream ou, const Date d)
{ou d._year 年 d._month 月 d._day 日 endl;return ou;//有返回值实现连续输出
}istream operator(istream in, Date d)
{while (1){in d._year d._month d._day;//检查日期是否合法if (d.CheckDate()){break;}else{cout 日期非法请重新输入 endl;}}return in;
}// d1 d2
//* this d
//这里需要修改*this
Date Date::operator(const Date d)
{_year d._year;_month d._month;_day d._day;return *this;//有返回值实现连续赋值
}
bool Date::operator(const Date d)const
{//年月日相等就相等return (_year d._year) (_month d._month) (_day d._day);
}bool Date::operator!(const Date d)const
{//1.直接写/*return (_year ! d._year)|| (_month ! _month)|| (_day ! d._day);*///2.代码复用return !(*this d);
}bool Date::operator(const Date d)const
{if (_year d._year){return true;}//年相等判断月if (_year d._year){if (_month d._month){return true;}//月相等判断天else if(_month d._month){if (_day d._day){return true;}}}return false;
}bool Date::operator(const Date d)const
{//代码复用return (*this d) || (*this d);
}bool Date::operator(const Date d)const
{代码复用return !((*this d) || (*this d));
}bool Date::operator(const Date d)const
{//代码复用return (*this d) || (*this d);
}//使用引用返回减少拷贝次数
Date Date::operator(int day)
{//特殊处理day0调用日期-天数if (day 0)//调用日期减天数{*this - (-day);}else{_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);//特殊处理day 0if (day 0){tmp - (-day);}else{//代码复用tmp day;}return tmp;
}Date Date::operator-(int day)
{if (day 0){*this (-day);}else{_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);//特殊处理day 0,调用天数if (day 0){tmp (-day);}else{//代码复用tmp - day;}return tmp;
}Date Date::operator()
{*this 1;return *this;
}Date Date::operator(int)//后面加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;
}//*this —— d
int Date::operator-(const Date d)const
{int flag 1;//标记默认前面的日期大Date max *this;Date min d;if (*this d){//后面的日期大重新赋值max d;min *this;flag -1;}int n 0;//计数//让小日期走到大日期进行计数while (min ! max){min;//或者min 1;n;}return n * flag;
} ♥♥♥本篇博客内容结束期待与各位优秀程序员交流有什么问题请私信♥♥♥ ♥♥♥如果这一篇博客对你有帮助~别忘了点赞分享哦~♥♥♥ ✨✨✨✨✨✨个人主页✨✨✨✨✨✨