当前位置: 首页 > news >正文

日期类的实现

头文件

#include<iostream>using namespace std;class Date
{friend ostream& operator<<(ostream& out, const Date& d);friend istream& operator>>(istream& in, Date& d);public:void Print() const{cout << _year << "-" << _month << "-" << _day << endl;}//类里面定义和申明在一起,该该函数为内联函数int GetMonthDay(int year, int month){//因为调用的比较频繁,每次调用的时候都会创建,所以加上static,定义在堆上上面,函数结束不会销毁static int ArrMonthDay[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;}else{return ArrMonthDay[month];}}//构造函数Date(int year, int month, int day);//判断是否相等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);//加天数Date&operator+=(int day);//加天数,但是本身不改变Date operator+(int day);//减天数Date& operator-=(int day);Date operator-(int day);//++d1Date&operator++();//d++Date operator++(int);int operator-(const Date& d);//输出private:int _year;int _month;int _day;
};

源文件

#include"Date.h"Date::Date(int year, int month, int day)
{_year = year;_month = month;_day = day;
}bool Date::operator==(const Date& d)
{return _year == d._year && _month == d._month&& _day == d._day;
}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){if (_day < d._day){return true;}}}return false;
}bool Date::operator<=(const Date& d)
{return *this == d || *this < d;
}bool Date::operator>(const Date& d)
{return !((*this) <= d);
}bool Date::operator!=(const Date& d)
{return !(*this == d);
}bool Date::operator>=(const Date& d)
{return !(*this < d);
}Date& Date::operator+=(int day)
{_day = _day + day;while (_day > GetMonthDay(_year, _month)){_day -= GetMonthDay(_year, _month);_month++;if (_month == 12){_month = 1;_year++;}}return *this;
}Date Date::operator+(int day){Date temp = *this;temp += (day);return  temp;}Date& Date::operator-=(int day){_day -= day;while (_day <= 0){_month--;if (_month == 0){_month = 12;_year--;}_day+= GetMonthDay(_year, _month);}return *this;}Date Date::operator-(int day)
{Date temp = *this;temp -= day;return temp;
}//++d
Date& Date::operator++()
{_day++;if (_day == GetMonthDay(_year, _month) + 1){_day = 1;_month++;if (_month == 12){_month = 1;_year++;}}return *this;
}Date Date::operator++(int)
{Date temp(*this);*this+=1;return *this;
}int Date::operator-(const Date& d)
{Date min = *this;Date max = d;if (*this > d){max = *this;min = d;}int n = 0;while (min != max){min++;n++;}return n;
}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;return in;
}

代码解释

输入输出

friend ostream& operator<<(ostream& out, const Date& d);friend istream& operator>>(istream& in, Date& d);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;return in;
}

上面的函数为友元函数,就是在函数声明的前面加上一个friend关键字,因为要在全局函数里面访问d对象的成员,但是在类外面是无法访问类里面的,但是变成朋友就可以了,好比朋友到家里面里,可以任意参观你的屋子一样

有朋友说,为什么不写在类的里里面,像下面这样

void operator<<(ostream& out);void Date::operator<<(ostream& out)
{out << _year << "年" << _month << "月" << _day << "日" << endl;
}

这样调用的时候就是下面的这样

d1.operator<<(cout);

但是如果不用下面,而用上面的那一个就是

cout<<d1;

其实两者都可以,但从逻辑性和方便性能上来看,定义为全局函数加上友元来得比较合适,这里需要记住得是,在运算符重载这里,操作数顺序和运算符号需要得操作数得顺序是一样的

还有一点要注意的是

返回类型为什么要写成ostream&和istream&,这里为什么不写成void 类型的,其实写成void 类型也行,但是写成void 类型只能操作一个对象

cout<<d1;           //可以
cout<<d1<<d2;       //不可以

这里和之前连续赋值是样的,从左到右结合后会有一个返回值,这里加上一个返回类型后,上面两种形式都可以

直接返回和引用返回

直接返回返回的是要返回对象的一个临时拷贝,引用返回返回返回的是对象的别名,相当于返回的就是对象本身,但是因为函数一结束函数栈帧就会销毁,引用返回再返回的话就已经不是该变量了,可能是返回值,所以对于函数结束要销毁的对象,不建议使用引用返回

使用引用返回仅仅是因为不像直接返回那样需要临时拷贝一个对象

关于这里,下面有一个例子

Date& Date::operator-=(int day){_day -= day;while (_day <= 0){_month--;if (_month == 0){_month = 12;_year--;}_day+= GetMonthDay(_year, _month);}return *this;}Date Date::operator-(int day)
{Date temp = *this;temp -= day;return temp;
}

上面的两个函数实现的功能是是一样的,第一个函数结束不涉及函数要返回对象的销毁,但是第二个函数结束返回的是temp,但是temp是函数结束需要被销毁的,所以第一个使用引用返回,减少拷贝,第二个使用直接返回

前置++和后置++

Date& Date::operator++()
{_day++;if (_day == GetMonthDay(_year, _month) + 1){_day = 1;_month++;if (_month == 12){_month = 1;_year++;}}return *this;
}//d++
Date Date::operator++(int)
{Date temp(*this);*this+=1;return *this;
}

当初设计者在设计的时候,为了区分前置加加和后置加加,选择在后置加加函数重载这里的参数里面加上一个int类型的参数

const修饰的成员

void test1()
{const Date d1(2024, 8, 24);d1.Print();
}

这里的函数调用会编译报错的,因为d1对像的const修饰 成为const Date*this,因为this本身具有常性,所以这里修饰的是 const Date* const this(当然这里对于这里的解释没有任何帮助),然后print函数里面的参数是Date* const this类型的,这里属于权限的放大,是不行的,只有权限的缩小是可以的,所以我们在Print函数后面加上一个const来修饰,让他变成const Date*const this,这样就行了

void Print() const
{cout << _year << "-" << _month << "-" << _day << endl;
}

但是,如果我们遇到cons修饰的怎么办,但是有的没有const ,所以有的函数我们可以加上cons,这样就无论有没有const,都不怕了,因为权限可以缩小,但是不可以放大,上面的有些函数没有加,可以加上

但是,这里如果要加上,要Date不用修改的,因为const Date*this,const修饰的是*this,就是this的指向内容,指向内容不能修改,const this修饰的this这个指针,this以后不能乱指

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • iptables: Chain Already Exists:完美解决方法
  • 通过因子分析识别消费者偏好的潜在因素的案例
  • 【异常错误】pycharm可以在terminal中运行,但是无法在run中运行(没有输出错误就停止了)
  • Java筑基之路:数组的深入了解学习!
  • 层序遍历判断完全二叉树
  • [LeetCode]46.全排列(python)
  • Ansys Rocky在电池制造行业应用
  • docker 里 oneapi 启动失败:failed to get gpt-3.5-turbo token encoder
  • 基于imx6ull平台移植ffmpeg3.4.5及ffmpeg验证
  • 数据分析案例-2024年裁员数据集可视化分析
  • 买智界R7,我扒出三点关键信息
  • 【C++ Primer Plus习题】4.7
  • SpringBoot文档之构建包的阅读笔记
  • php与nginx的高速缓存
  • linux文件——用户缓冲区——概念深度探索、IO模拟实现
  • .pyc 想到的一些问题
  • [case10]使用RSQL实现端到端的动态查询
  • 【108天】Java——《Head First Java》笔记(第1-4章)
  • 【跃迁之路】【699天】程序员高效学习方法论探索系列(实验阶段456-2019.1.19)...
  • Bytom交易说明(账户管理模式)
  • CSS实用技巧干货
  • C语言笔记(第一章:C语言编程)
  • java B2B2C 源码多租户电子商城系统-Kafka基本使用介绍
  • Less 日常用法
  • Netty 框架总结「ChannelHandler 及 EventLoop」
  • select2 取值 遍历 设置默认值
  • SpiderData 2019年2月16日 DApp数据排行榜
  • SpiderData 2019年2月23日 DApp数据排行榜
  • SpringCloud(第 039 篇)链接Mysql数据库,通过JpaRepository编写数据库访问
  • vue-router的history模式发布配置
  • 第2章 网络文档
  • 关于字符编码你应该知道的事情
  • 理解在java “”i=i++;”所发生的事情
  • 利用DataURL技术在网页上显示图片
  • 码农张的Bug人生 - 见面之礼
  • 前端每日实战:61# 视频演示如何用纯 CSS 创作一只咖啡壶
  • 入门级的git使用指北
  • 设计模式 开闭原则
  • 数组大概知多少
  • 消息队列系列二(IOT中消息队列的应用)
  • 用mpvue开发微信小程序
  • media数据库操作,可以进行增删改查,实现回收站,隐私照片功能 SharedPreferences存储地址:
  • 关于Android全面屏虚拟导航栏的适配总结
  • # linux 中使用 visudo 命令,怎么保存退出?
  • #define与typedef区别
  • #systemverilog# 之 event region 和 timeslot 仿真调度(十)高层次视角看仿真调度事件的发生
  • #我与Java虚拟机的故事#连载16:打开Java世界大门的钥匙
  • $.extend({},旧的,新的);合并对象,后面的覆盖前面的
  • (02)Hive SQL编译成MapReduce任务的过程
  • (13)Latex:基于ΤΕΧ的自动排版系统——写论文必备
  • (HAL库版)freeRTOS移植STMF103
  • (二)丶RabbitMQ的六大核心
  • (附源码)spring boot网络空间安全实验教学示范中心网站 毕业设计 111454
  • (附源码)ssm教师工作量核算统计系统 毕业设计 162307
  • (附源码)计算机毕业设计SSM疫情社区管理系统