类和对象(拷贝构造和运算符重载)下
这一集的主要目标先是接着上一集讲完日期类。然后再讲一些别的运算符的重载,和一些语法点。
这里我把这一集要用的代码先放出来:(大家拷一份代码放在编译器上先)
Date.h
#include <iostream>
#include <cassert>
using std::cout;
using std::cin;
using std::endl;
using std::ostream;
using std::istream;
class Date
{
private:
int _year;
int _month;
int _day;
public:
//构造函数
Date(int year=2025,int month=4,int day=30);
//拷贝构造函数//日期类可以不写拷贝构造函数,编译器写的符合我们的要求
Date(const Date& dd);
//析构函数就不写了,日期类并不需要
//打印
void Print();
//获取当年当月的天数
int monthday(int year,int month);
//比较日期大小
bool operator==(const Date& other);
bool operator!=(const Date& other);
bool operator>(const Date& other);
bool operator<(const Date& other);
bool operator>=(const Date& other);
bool operator<=(const Date& other);
//加减运算
Date& operator+=(int day);//加上n天后的日期是多少
Date operator+(int day);
Date& operator-=(int day);//n天前的日期是多少
Date operator-(int day);
Date& operator++();//前置++
Date operator++(int);//后置++
Date& operator--();
Date operator--(int);
int operator-(const Date& other);//两个日期相隔几天
//赋值重载
Date& operator=(const Date& other);
//流插入重载//声明为友元函数
friend ostream& operator<<(ostream& out, const Date& dd);
//流提取重载
friend istream& operator>>(istream& in, Date& dd);
//&取地址重载
Date* operator&();
//const取地址&重载
const Date* operator&() const;
};
ostream& operator<<(ostream& out, const Date& dd);
istream& operator>>(istream& in, Date& dd);
Date.cpp
#include "Date.h"
Date::Date(int year,int month,int day)
{
_year=year;
_month=month;
_day=day;
if (_year < 1 ||
_month < 1 || _month > 12 ||
_day < 1 || _day > monthday(_year, _month))
{
//assert(false);
Print();
cout << "日期非法" << endl;
}
}
Date::Date(const Date& dd)
{
_year=dd._year;
_month=dd._month;
_day=dd._day;
}
void Date::Print()
{
cout<<_year<<'_'<<_month<<'_'<< _day<<endl;
}
int Date::monthday(int year,int month)
{
assert(year>=1 && month>=1 && month<=12);
int day[13]={0,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 day[month];
}
}
bool Date::operator==(const Date& other)
{
return _year==other._year
&& _month==other._month
&& _day==other._day;
}
bool Date::operator!=(const Date& other)
{
return !(*this==other);
}
bool Date::operator>(const Date& other)
{
if(_year>other._year)
{
return true;
}
if(_year==other._year && _month>other._month)
{
return true;
}
if(_year==other._year && _month==other._month && _day>other._day)
{
return true;
}
return false;
}
bool Date::operator<(const Date& other)
{
return !(*this>=other);
}
bool Date::operator>=(const Date& other)
{
return (*this>other||*this==other);
}
bool Date::operator<=(const Date& other)
{
return !(*this>other);
}
Date& Date::operator+=(int day)
{
if(day<0)
{
return *this-=(-day);
}
_day+=day;
while(_day> monthday(_year,_month))
{
_day-= monthday(_year,_month);
_month+=1;
if(_month>12)
{
_month=1;
_year+=1;
}
}
return *this;
}
Date Date::operator+(int day)
{
Date tmp(*this);
tmp+=day;
return tmp;
}
Date& Date::operator-=(int day)
{
if(day<0)
{
return *this+=(-day);
}
_day-=day;
while(_day<=0)
{
_month-=1;
if(_month<1)
{
_month=12;
_year-=1;
}
_day+= monthday(_year,_month);
}
return *this;
}
Date Date::operator-(int day)
{
Date tmp(*this);
tmp-=day;
return tmp;
}
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& other)
{
int day=0;
Date tmp(other);
while(*this!=tmp)
{
if(*this>tmp)
{
++tmp;
day++;
}
if(*this<tmp)
{
--tmp;
day++;
}
}
return day;
}
Date& Date::operator=(const Date& other)
{
if(this != &other)//防止自己给自己赋值
{
_year=other._year;
_month=other._month;
_day=other._day;
}
return *this;
}
//流插入重载
ostream& operator<<(ostream& out, const Date& dd)
{
out<<dd._year<<'_'<<dd._month<<'_'<<dd._day<<endl;
return out;
}
//流提取重载
istream& operator>>(istream& in,Date& dd)
{
in>>dd._year>>dd._month>>dd._day;
return in;
}
//&取地址重载
Date* Date::operator&()
{
return this;
}
//const取地址&重载
const Date* Date::operator&() const
{
return this;
}
main.cpp
#include "Date.h"
void Test()
{
Date d1;
Date d2(1999,10,17);
Date d3;
int day=d1-d2;
int day1=d3-d1;
cout<<day<<endl<<day1<<endl;
}
void Test1()
{
Date d1;
cout<<d1<<endl;
cin>>d1;
cout<<d1<<endl;
}
int main()
{
Test();
return 0;
}
大家想去验证结果的时候可以去网上搜:日期计算器
我会按照头文件函数声明的顺序讲解函数逻辑,以及语法点:
日期类函数顺序讲解:
-
int monthday(int year,int month);
-
bool operator==(const Date& other); bool operator!=(const Date& other);
-
bool operator>(const Date& other); bool operator<(const Date& other); bool operator>=(const Date& other); bool operator<=(const Date& other);
-
Date& operator+=(int day);//加上n天后的日期是多少 Date operator+(int day); Date& operator-=(int day);//n天前的日期是多少 Date operator-(int day);
-
Date& operator++();//前置++ Date operator++(int);//后置++ Date& operator--(); Date operator--(int);
-
int operator-(const Date& other);//两个日期相隔几天
-
//赋值重载 Date& operator=(const Date& other);
这个上一集有讲, 这一集就不讲了。
那么到这里为止, 日期类的一些基础逻辑函数都已经讲完了, 现在来填一下前面埋的坑.
好, 这部分的坑填完了, 接着讲一些别的重载:
-
//流插入重载//声明为友元函数 friend ostream& operator<<(ostream& out, const Date& dd); //流提取重载 friend istream& operator>>(istream& in, Date& dd);
有的同学觉得, 诶, 这不会和位移运算符<<这些冲突嘛? 不会的, 编译器没那么傻. 而且能用位移运算符的不也就整型嘛. 所以不会有问题的.
在 C++ 里,const
成员函数是一种特殊的成员函数,它的关键作用在于保证该函数不会对调用它的对象的成员变量进行修改。(一句话就是: 只要是你不修改对象本身的函数, 你都给我加上const)
定义与语法
在成员函数的参数列表之后添加const
关键字,就能将其声明为const
成员函数。其基本语法如下:
class ClassName {
public:
// 返回类型 函数名(参数列表) const
ReturnType functionName(ParameterList) const {
// 函数体
}
};
注意事项
this
指针:在const
成员函数内部,this
指针是一个指向const
对象的指针,这就保证了函数内部不能通过this
指针来修改对象的成员变量。- 函数重载:
const
成员函数可以和非const
成员函数进行重载。当调用成员函数时,编译器会依据对象是否为const
来选择合适的函数。(注意昂, 就要用到这一点了)
这里const成员函数其实有一个权限问题, 说白了就是const修饰之后不就是多了一道枷锁嘛. 你不能说我给你带上了锁, 你还给我解开跑了, 这是不行的.
权限只能平移或缩小, 不能放大. 这就像市长可以可以管理市内业务(平移), 也可以管理一个村子(缩小), 但是你没有权限去管省长干的事情. (大概是这个意思, 不严谨的举例哈)
-
//&取地址重载 Date* operator&(); //const取地址&重载 const Date* operator&() const;
- 函数重载:
const
成员函数可以和非const
成员函数进行重载。当调用成员函数时,编译器会依据对象是否为const
来选择合适的函数。看到没.