wordpress 哪些网站,百讯网站建设,高大上强企业网站,深圳分销网站制作目录 前言
日期类的实现
日期的获取
日期的比较
const成员函数
日期的加减
日期的加等
日期的减等 日期的加减
日期的加加减减
日期的相减
流插入和提取的重载
友元
友元的特点 日期类代码 总结 前言
前面我们介绍了C中类和对象的相关知识和六个默认成员函数中类和对象的相关知识和六个默认成员函数在此基础上我们可以用C实现一个日期类这样可以帮助我们更加深入理解C中的知识点如果文章中有不懂的可以参考之前的文章
C从入门到入土三--6个默认成员函数
C从入门到入土二——初步认识类与对象
日期类的实现
我们在创建一个项目之前首先要知道这个项目要完成什么功能以日期类为例我们要实现日期的比较日期的加减以及日期的获取等功能所以根据之前学的运算符重载等方面的知识我们可以很轻松地在Date.h文件中声明这个类所要实现的各种功能如下所示
#pragma once
#includeiostream
using namespace std;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);int GetMonthDay(int year, int month){int GetMonthDayArry[13] { 0,31,30,31,30,31,30,31,31,30,31,30,31 };if (2 month (year % 4 0 year % 100 ! 0 )|| year % 400 0){return 29;}else{return GetMonthDayArry[month];}}bool CheckDate();void Print()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;Date operator(int day);Date operator(int day)const;Date operator-(int day);int operator-(const Date d)const;Date operator();Date operator(int);Date operator--();Date operator--(int);
private:int _year;int _month;int _day;
};ostream operator(ostream out, const Date d);
istream operator(istream in, Date d); 下面我将逐一分析实现相关的功能。
日期的获取
我们创建好一个日期类后首先要获取里面的日期于是我们创建了一个GetMonthDay的成员函数可以看到它的返回值是int在函数里面我们创建了一个名为GetMonthDayArry的数组这个数组里面存放了每个月的天数为了方便通过传月份来获取日期我们给这个数组的数据个数定为13但是我们此时面临一个问题遇到闰年的2月该怎么办呢那么此时我们就要特殊情况特殊处理闰年的判断规则是四年一润百年不润四百年再润于是我们便可以轻松写下如下代码
int GetMonthDay(int year, int month)
{int GetMonthDayArry[13] { 0,31,30,31,30,31,30,31,31,30,31,30,31 };if (2 month (year % 4 0 year % 100 ! 0 )|| year % 400 0){return 29;}else{return GetMonthDayArry[month];}
}
日期的比较
通过运算符重载的相关知识我们知道作为类的成员函数重载时有一个隐藏的this指针因此我们只需要显示传一个参数因此我们就有了以下定义
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; 由于C的语法我们在实现上述逻辑时只需要实现其中的两个其他的直接复用就可以轻松完成以上任务我们在这里只实现小于和等于两个逻辑其余直接复用即可请参考以下代码
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){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);
}
bool Date::operator(const Date d)const
{return (*this d || *this d);
}
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);
}
const成员函数
我们发现在以上几个日期的比较函数的后面我们都加上了const这是为什么呢 实际上我们将成员函数后面加const的函数称为const成员函数从表面上看const是在修饰类的成员函数实际上是在修饰该成员函数隐藏的this指针表明在该成员函数中不能对类的任何成员进行修改即只要不修改成员的就可以在后面加上const
日期的加减
日期的加等
我们首先来介绍日期的加等日期的加等原则就是进位法即将天数全加上去如果超过该月的天数就将该月的天数减去此时月数进一如果超过12个月那么年数进一于是我们就有了以下代码
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;
}
注意我们看到此时我们是用引用返回 在前面我们知道返回对象生命周期到了会析构我们就传值返回返回对象生命周期到了不会析构我们就传引用返回。而此时我们要获取的是加完之后的值因此我们要传引用返回
日期的减等
日期减等的逻辑与加等类似即将天数全部减去后如果天数小于0那么就将前一个月的天数加上去如果月份为0那么就置为12此时年份退一于是我们便有了以下代码
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)const
{Date tmp *this;tmp day;return tmp;
}
Date Date::operator-(int day)const
{Date tmp *this;tmp - day;return tmp;
}
日期的加加减减
由于函数重载的规则我们在重载或--操作符时为了区分是前置还是后置C规定后置或后置--多了一个int的操作数加以区分。由于前置或前置--返回的是或--之后的值因此我们要传引用返回而后置则返回之前的值所以传值返回于是我们可以写下以下代码
//前置
Date Date::operator()
{return *this 1;
}
//后置
Date Date::operator(int)
{Date tmp *this;return tmp 1;
}
//前置--
Date Date::operator--()
{return *this - 1;
}
//后置--
Date Date::operator--(int)
{Date tmp *this;return tmp - 1;
}
日期的相减
日期的相减返回的是两日期之前的差值所以用int返回我们可以写下以下代码
int Date::operator-(const Date d)const
{Date max *this;Date min d;int flag 1;int n 0;if (*this d){max d;min *this;}while (min ! max){min;n;}return n * flag;
} 至此一个完整的日期类就呈现了出来。
流插入和提取的重载
但是我们在Date.h文件中还有以下两个没有实现那这两个是什么东西呢
ostream operator(ostream out, const Date d);
istream operator(istream in, Date d); 实际上这是流插入和流提取操作符的重载那么为什么要用流插入和流提取呢实际上是因为C中的流插入和提取存在缺陷。我们发现与C语言中的printf和scanf不同的是cout和cin可以自动识别变量的类型但这仅仅只能识别内置类型自定义类型的输入和输出时不能直接使用cout和cin那么我们该怎么解决这个问题呢于是C语法上支持了和的重载。但是为什么我们选择将其定义在类的外面呢实际上是为了可读性所采取的操作但是我们将其定义在类外无法访问私有为了解决这个问题我们引入了友元这个概念。
友元
什么是友元呢友元提供了一种突破封装的方式有时提供了便利。但是友元会增加耦合度破坏了封装所以友元不宜过多使用。
我们还是回归上述问题为什么将其重载为成员函数会降低可读性呢我们现在尝试去重载operator然后发现没办法将operator重载成成员函数。因为cout的输出流对 象和隐含的this指针在抢占第一个参数的位置。this指针默认是第一个参数也就是左操作数了。但是实际使用 中cout需要是第一个形参对象才能正常使用。所以要将operator重载成全局函数。但又会导致类外没办 法访问成员此时就需要友元来解决。operator同理。
友元的特点
1.友元函数可访问类的私有和保护成员但不是类的成员函数 友元函数不能用const修饰
2.友元函数可以在类定义的任何地方声明不受类访问限定符限制
3.一个函数可以是多个类的友元函数
4.友元函数的调用与普通函数的调用原理相同
在有了上述知识的铺垫后我们可以将流插入流提取操作符的重载函数写出代码如下
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;
} 日期类代码
整个Date.c的代码如下
bool Date::CheckDate()
{if (_month 1 || _month12||_day1||_dayGetMonthDay(_year,_month)){return false;}else{return true;}
}
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;
}
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){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);
}
bool Date::operator(const Date d)const
{return (*this d || *this d);
}
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);
}Date Date::operator(int 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)const
{Date tmp *this;tmp day;return tmp;
}
Date Date::operator-(int day)
{_day - day;while (_day 0){--_month;_day GetMonthDay(_year, _month);if (_month 0){_month 12;--_year;}}return *this;
}int Date::operator-(const Date d)const
{Date max *this;Date min d;int flag 1;int n 0;if (*this d){max d;min *this;}while (min ! max){min;n;}return n * flag;
}Date Date::operator()
{return *this 1;
}
Date Date::operator(int)
{Date tmp *this;return tmp 1;
}
Date Date::operator--()
{return *this - 1;
}
Date Date::operator--(int)
{Date tmp *this;return tmp - 1;
}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;
} 总结
感谢您能在百忙之中抽出时间来看鄙人的文章相信看完文章的你会对C的类与对象有一个更清楚的认识受限于本人的水平可能文章中会存在一些问题欢迎各位指正如果本篇文章对您有所帮助的话希望能给我点赞评论加关注您的支持就是对我创作的最大鼓励。