C++类与对象---日期类
日期类是类与对象的常用类型之一,也是用来练习类与对象的各项技巧的一个好类型。
本文较为详细得实现日期类的各个功能,日期类包含了:1.日期之间的相差多少天,2.获取该年份某月的天数,3.日期的输入输出,4.日期之间大小的比对,5.增加x天后的日期
日期类的实现:
日期类的基础成员和初始化(构造函数)和拷贝构造:
获取该年所有月的天数:
日期的增加和减少:
日期之间的对比:
日期的自增和自减:
日期之间相差多少天:
重载日期的输入和输出 :
日期类的实现:
日期类的主要功能就是日期之间的相差天数和往后多少天后日期是多少,而我们就实现这些功能
日期类的基础成员和初始化(构造函数)和拷贝构造:
日期类的基础成员自然就是年,月,日
1.在头文件中定义一个类取名Date
2.定义三个成员变量int类型_year,_mouth,_day
3.成员函数(构造)对其初始化并添加缺省值
4.日期类没有涉及空间申请,所以拷贝构造和析构函数都可以不写,编译器自己生成的就够用
运用的函数技巧:默认构造,缺省参数,列表初始化
class Date { public: Date(int year=1, int mouth=1, int day=1) //全缺省参数保证每个变量都有值 :_year(year) ,_mouth(mouth) ,_day(day) {} private: //三个变量设为私有 int _year; int _mouth; int _day; }
获取该年所有月的天数:
假设现在实例化出一个日期类对象,进行日期的增加那么这时候就需要获取月份的天数了(现在不考虑年月日初始化时的超过问题,此问题会在后面进行解决)
获取天数的次数比较频繁且代码量少可以设为内联函数(inline)
现在只要写一个获取日期的成员函数即可:
int GetMouthDay(int year, int mouth) { static int mouthday[13] = {-1,31,28,31,30,31,30,31,31,30,31,30,31}; if ((mouth == 2) && ((0 == year % 4 && year % 100 != 0) || (0 == year % 400))) { return 29; } return mouthday[mouth]; }
日期的增加和减少:
自定义类型的+=和-=需要使用运算符重载进行编写
1.重载+=和-=运算符
2.重新定义内部逻辑
运用的技巧:运算符重载
Date& operator+=(int day) { if (day < 0) //假设天数给负数那么直接调用-=函数就可以了 { return *this -= (-day); } _day += day; //天数加天数 while (_day > GetMouthDay(_year, _mouth)) //判断天数是否超过当月天数 { _day -= GetMouthDay(_year, _mouth); //减去当月月数 ++_mouth; //月数自加 if (_mouth == 13) //判断月数是否超过12个月 { _mouth = 1; ++_year; //年数加加 } } return *this; } date& date::operator-=(int day) { if (day < 0) //负负得正直接调用+=函数即可 { return *this += (-day); } _day -= day; //判断天数是否为负数 while (_day <= 0) { _mouth--; //月数减减 if (_mouth < 1) //判断月是否为一月 { _mouth = 12; _year--; //年数减减 } _day += GetMouthDay(_year, _mouth); //加上该月的天数 } return *this; }
日期之间的对比:
对比两个日期之间的大小,同样也需要重载运算符,它的对比也需要使用运算符重载进行编写和复用
这里至少需要重载两个运算符,一个==和<或>运算符,因为>=和<=会需要两个运算符重载的复用
运用的技巧:运算符重载,代码复用
bool operator<(const Date& da)const { if (_year < da._year) //先判断年 { return true; } else if (_year == da._year) //如果年份相等 { if (_mouth < da._mouth) //比月份 { return true; } else if (_mouth == da._mouth) //月份相等 { return _day < da._day; //比天数 } } return false; } bool operator==(const Date& da)const //等于比较简单就全部相等 { return (_year == da._year)&&(_mouth == da._mouth)&&(_day == da._day); } //下面是代码的复用 bool operator<=(const Date& da)const { return (*this<da)||(*this==da); } bool operator>(const Date& da)const { return !(*this<da); //<的逻辑取反 } bool operator>=(const Date& da)const { return !(*this<da)||(*this==da); } bool operator!=(const Date& da)const { return !(*this==da); }
日期的自增和自减:
依旧是使用运算符重载进行编写,分别是前置++和--,后置++和--,这里进行的+=和-=行为都会自动调用重载过后的运算符
运用的技巧:运算符重载,后置++和--需要增加参数
//前置++ Date& operator++() { *this += 1; return *this; } //后置++ Date operator++(int) { date temp = *this; *this += 1; return temp; } //前置-- Date& operator--() { *this -= 1; return *this; } //后置-- Date operator--(int) { date temp = *this; *this -= 1; return temp; }
日期之间相差多少天:
日期减日期相差返回天数,重载一个"-"运算符,重新定义"-",且日期类没有涉及到申请空间,所以编译器自己生成的拷贝构造就可以满足需求,当然作为练习自己实现也没关系
/*Date(const Date&da) { _year=da._year; _mouth=da._mouth; _day=da._day; }*/ int operator-(const Date& da)const { int flag=-1; //用来判断相差天数的正负数 //flag给正下面if语句里给负也行,看个人喜好 Date max=*this; //使用假设法 Date min=da; if(*this<da) { max = da; min =*this; flag = 1; } int ret = 0; while (min != max) //不断++直至两者天数相等 { ++min; ++ret; } return ret * flag; }
重载日期的输入和输出 :
日期肯定都是通过键盘输入不可能每次都自己给固定的值,所以我们需要重载cin;输出是一个一个访问很怪所以重新定义把这一层包装起来,所以重载cout
现在输入重载了,检测日期是否违规的函数也有了就可以在构造函数上解决这个日期违规的问题了
注意:
1.cout和cin应该重载为全局函数然后设为该类的友元(friend)
2.同时写一个判断月份和天数是否违规的成员函数在重载cin的时候调用解决输入日期违规的问题
3.cout的类型是ostream;cin的类型是istream
date::date(int year , int mouth , int day ) { _year = year; _mouth = mouth; _day = day; if (!Checkdate()) { cout << "非法日期" << endl; print(); cout << "请重新输入" << endl; cin >> *this; } } bool Checkdate() { if (_mouth < 1 || _mouth>12 || _day<1 || _day>GetMouthDay(_year, _mouth)) { return false; } else { return true; } } ostream& operator<<(ostream& out, const Date& da) { cout << da._year << "年" << da._mouth << "月" << da._day << "日"<<endl; return out; } istream& operator>>(istream& in, Date& da) { while (1) { cout << "请输入日期>:"; cin >> da._year >> da._mouth >> da._day; if (!da.Checkdate()) //调用函数进行月份和天数的判断 { cout << "非法日期" << endl; da.print(); cout << "请重新输入" << endl; //重新输入 } else { break; } } return in; }
一个日期类就完成了下面是全部代码,使用了声明定义分离
//头文件
#pragma once
#include <iostream>
using namespace std;
class date
{
friend ostream& operator<<(ostream& out, const date& da);
friend istream& operator>>(istream& in, date& da);
public:
//构造函数
date(int year = 1, int mouth = 1, int day = 1);
int GetMouthDay(int year, int mouth)
{
static int mouthday[13] = {-1,31,28,31,30,31,30,31,31,30,31,30,31};
if ((mouth == 2) && ((0 == year % 4 && year % 100 != 0) || (0 == year % 400)))
{
return 29;
}
return mouthday[mouth];
}
void print()const;
bool Checkdate();
date& operator+=(int day);
date operator+(int day)const;
date& operator-=(int day);
date operator-(int day)const;
int operator-(const date& da)const;
//前置++
date& operator++();
//后置++
date operator++(int);
//前置--
date& operator--();
//后置--
date operator--(int);
bool operator<(const date&da)const;
bool operator<=(const date& da)const;
bool operator>(const date& da)const;
bool operator>=(const date& da)const;
bool operator==(const date& da)const;
bool operator!=(const date& da)const;
private:
int _year;
int _mouth;
int _day;
};
ostream& operator<<(ostream& out, const date& da);
istream& operator>>(istream&
#include "head.h"
date::date(int year , int mouth , int day )
{
_year = year;
_mouth = mouth;
_day = day;
if (!Checkdate())
{
cout << "非法日期" << endl;
print();
cout << "请重新输入" << endl;
cin >> *this;
}
}
void date::print()const
{
cout << _year << "年" << _mouth << "月" << _day << "日" << endl;
}
date& date::operator+=(int day)
{
if (day < 0)
{
return *this -= (-day);
}
_day += day;
while (_day > GetMouthDay(_year, _mouth))
{
_day -= GetMouthDay(_year, _mouth);
++_mouth;
if (_mouth == 13)
{
_mouth = 1;
++_year;
}
}
return *this;
}
date date::operator+(int day) const
{
date st = *this;
st += day;
return st;
}
date& date::operator-=(int day)
{
if (day < 0)
{
return *this += (-day);
}
_day -= day;
while (_day <= 0)
{
_mouth--;
if (_mouth < 1)
{
_mouth = 12;
_year--;
}
_day += GetMouthDay(_year, _mouth);
}
return *this;
}
date date::operator-(int day)const
{
date st = *this;
st -= day;
return st;
}
//前置++
date& date::operator++()
{
*this += 1;
return *this;
}
//后置++
date date::operator++(int)
{
date temp = *this;
*this += 1;
return temp;
}
//前置--
date& date::operator--()
{
*this -= 1;
return *this;
}
//后置--
date date::operator--(int)
{
date temp = *this;
*this -= 1;
return temp;
}
bool date::operator<(const date& da)const
{
if (_year < da._year)
{
return true;
}
else if (_year == da._year)
{
if (_mouth < da._mouth)
{
return true;
}
else if (_mouth == da._mouth)
{
return _day < da._day;
}
}
return false;
}
bool date::operator<=(const date& da)const
{
return *this < da || *this == da;
}
bool date::operator>(const date& da)const
{
return !(*this < da);
}
bool date::operator>=(const date& da)const
{
return *this > da || *this == da;
}
bool date::operator==(const date& da)const
{
return _year == da._year
&& _mouth == da._mouth
&& _day == da._day;
}
bool date::operator!=(const date& da)const
{
return _year != da._year
|| _mouth != da._mouth
|| _day != da._day;
}
int date::operator-(const date& da)const
{
int flag = -1;
date max = *this;
date min = da;
if (*this < da)
{
max = da;
min =*this;
flag = 1;
}
int ret = 0;
while (min != max)
{
++min;
++ret;
}
return ret * flag;
}
bool date::Checkdate()
{
if (_mouth < 1 || _mouth>12 || _day<1 || _day>GetMouthDay(_year, _mouth))
{
return false;
}
else
{
return true;
}
}
ostream& operator<<(ostream& out, const date& da)
{
cout << da._year << "年" << da._mouth << "月" << da._day << "日"<<endl;
return out;
}
istream& operator>>(istream& in, date& da)
{
while (1)
{
cout << "请输入日期>:";
cin >> da._year >> da._mouth >> da._day;
if (!da.Checkdate())
{
cout << "非法日期" << endl;
da.print();
cout << "请重新输入" << endl;
}
else
{
break;
}
}
return in;
}
//功能测试
#include "head.h"
void test()
{
date st, st1;
date st2(2024,5,65);
cin >> st >> st1;
st++;
cout<<"增加后的日期:" << st << endl;
st.print();
st1.print();
cout <<"相差日期:"<< st - st1 << endl;
}
int main()
{
test();
return 0;
}
调用结果:
本篇就到这里了,希望能够为你在练习类与对象上提供帮助,感谢阅读