文章目录
运算符重载
c++中在自定义类型进行比较时给了运算符重载这个概念
让自定义类型可以进行运算符操作
在类中 定义运算符重载: operator + 符号
拿年月日这个类来说
class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
void Print()
{
cout << _year << "/" << _month << "/" << _day << endl;
}
//因为在类中 函数中有一个this 隐藏的变量
bool operator>(const Date& y)
{
if (_year > y._year)
{
return true;
}
else if (_year == y._year && _month > y._month)
{
return true;
}
else if (_year == y._year && _month == y._month && _day > y._day)
{
return true;
}
return false;
}
bool operator==(const Date& y)
{
return _day == y._day && _month == y._month && _year == y._year;
}
/*int operator-(const Date& d)
{
}*/
int GetMonthDay(int year, int month)
{
static int days[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30,31 };
int day = days[month];
if (month == 2
&& ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
{
day += 1;
}
return day;
}
Date& operator+=(int day)
{
_day += day;
while (_day > GetMonthDay(_year, _month))//判断_day 是否大于当月的天数 如果大于 月++
{
_month++;
_day -= GetMonthDay(_year, _month);
if (_month > 12)
{
_year++;
_month -= 12;
}
}
return *this;
}
Date operator+(int day)
{
Date tmp(*this);
tmp += day;//用tmp来接收 this传的类 调用+= 之后类不变
return tmp;
}
private:
int _year;
int _month;
int _day;
};
因为类中是有隐藏的 this , 所以 只用传一个对象
运算符中的前置++和后置++/前置–和后置–
因为前置++是先++后使用,所以要传改变的值回去
Date& Date::operator++()//前置++
{
*this += 1;
return *this;
}
后置++是先使用后++,所有要用一个对象来接受然后传对象,但是本身传的对象是进行了改变的,并且为了和前置++区分,c++规定了,要在传值的时候传一个空的值
//后置++ 因为要构成重载 所有函数内要 int
//特殊处理
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;
}
特殊运算符 <<(流插入) / >>(流提取)
因为这两个比较特殊 要有单独的规定
流插入本身只能插入内置类型 ,我们要单独在全局里面重载一个插入
ostream& operator<<(ostream& out, const Date& d)
{
out << d._year << "/" << d._month << "/" << d._day << endl;
return out;
}
istream& operator>>(istream& in,Date& d)
{
in >> d._year >> d._month >> d._day;
return in;
}
ostream 是一个类 cout是这个类的对象 所以要调用这个类才能进行流插入
istream 是一个类 cin是这个类的对象 所有要调用这个类才能进行流提取
返回是返回对应的流入的对象是因为 可以二次插入/提取
为什么是定义全局的<< / >>
因为如果是在类里面 ,类里面的成员函数都会 有一个隐藏的 this 他占据
函数传参的第一个位置 所以 如果在类里面写流插入 / 流提取的话
那么他最后只能
对象<< cout 这样子插入
对象>> cin 这样子提取
可读性很差所以
全局怎么调用类里面的私有?
友元函数: friend +函数声明 叫友元函数 友元函数可以访问类里面的私有
const定义对象
如果const 定义一个变量时 类里面的成员函数不能使用
为了避免这个问题 c++推出了 在类里面的函数 中 需要 用到 const 定义的对象 使用成员函数的方法 , 在成员函数 后面加 const
需要有修改的函数 不用加 const
#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>GetMonthDay(_year, _month))
{
//perror("日期非法");
cout << "日期非法" << endl;
exit(-1);
}
}
int GetMonthDay(int year, int month)
{
static int days[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30,31 };
int day = days[month];
if (month == 2
&& ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
{
day += 1;
}
return day;
}
Date& Date::operator=(const Date& d)
{
//避免自己给自己赋值
if (this != &d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
return *this;
}
Date& Date::operator+=(int day)
{
if (day < 0)
{
return *this -= (-day);
}
_day += day;
while (_day > GetMonthDay(_year, _month))//判断_day 是否大于当月的天数 如果大于 月++
{
_month++;
_day -= GetMonthDay(_year, _month);
if (_month > 12)
{
_year++;
_month -= 12;
}
}
return *this;
}
Date& Date::operator-=(int day)
{
if (day < 0)
{
return *this += (-day);
}
_day -= day;
while (_day <= 0)
{
_month--;
if (_month <= 0)
{
_month += 12;
_year--;
}
_day += GetMonthDay(_year, _month);
}
return *this;
}
bool Date::operator==(const Date& y) const
{
return _day == y._day && _month == y._month && _year == y._year;
}
bool Date::operator>(const Date & y) const
{
return !(*this <= y);
/*if (_year > y._year)
{
return true;
}
else if (_year == y._year && _month > y._month)
{
return true;
}
else if (_year == y._year && _month == y._month && _day > y._day)
{
return true;
}
return false;*/
}
bool Date::operator<(const Date& y) const
{
return !(*this >= y);
/*if (_year < y._year)
{
return true;
}
else if (_year == y._year && _month < y._month)
{
return true;
}
else if (_year == y._year && _month == y._month && _day < y._day)
{
return true;
}
return false;*/
}
bool Date::operator<=(const Date& y) const
{
if (_year <= y._year)
{
return true;
}
else if (_year == y._year && _month <= y._month)
{
return true;
}
else if (_year == y._year && _month == y._month && _day <= y._day)
{
return true;
}
return false;
}
bool Date::operator>=(const Date& y) const
{
if (_year >= y._year)
{
return true;
}
else if (_year == y._year && _month >= y._month)
{
return true;
}
else if (_year == y._year && _month == y._month && _day >= y._day)
{
return true;
}
return false;
}
bool Date::operator!=(const Date& y) const
{
return !(*this == y);
}
Date Date::operator+(int day)
{
Date tmp(*this);
tmp += day;//用tmp来接收 this传的类 调用+= 之后类不变
return tmp;
}
Date Date::operator-(int day)
{
Date tmp(*this);
tmp -= day;
return tmp;
}
int Date::operator-(const Date& d)
{
int flag = 1;
Date max = *this;
Date min = d;
if (*this < d)
{
max = d;
min = *this;
flag = -flag;
}
int n = 0;
while (max != min)
{
++n;
++min;
}
return n * flag;
}
Date& Date::operator++()//前置++
{
*this += 1;
return *this;
}
//后置++ 因为要构成重载 所有函数内要 int
//特殊处理
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;
}
ostream& operator<<(ostream& out, const Date& d)
{
out << d._year << "/" << d._month << "/" << d._day << endl;
return out;
}
istream& operator>>(istream& in,Date& d)
{
in >> d._year >> d._month >> d._day;
return in;
}
构造函数的补充
在构造函数里面 可以在函数内初始化,也可以在函数外进行初始化
为什么要有函数外初始化呢?
c++中的引用、const 成员变量、 类 无法在函数内初始化
初始化外 叫初始化列表
: 开头 ,换行
函数内外可以同时使用
有些检查的要在函数体内
尽量使用初始化列表
struct A
{
public:
A(int a)
:_a(a)
{
}
private:
int _a;
};
class Date
{
public:
Date(int year, int month, int day)
//初始化列表
//尽量使用初始化列表
//构造函数不能只要初始化列表还要函数体内
//有些检查的要在函数体内
//:开始 ,换行
//列表和函数内可以混着用
//但是 引用 和 const 必须在列表定义
:_m(year)
, _n(1)
, _aa(10)
{
//函数体内初始化
//剩下的这三个成员没有在初始化列表中显示写出来定义
//但是他也会定义,只是内置类型他会给随机值
//如果是自定义类型他会调用自己的默认构造函数
_year = year;
_month = month;
_day = day;
}
private:
//初始化是按声明走的
int _year;
int _month;
int _day;
//引用 是无法在构造函数内初始化
int& _m;
//const 也无法在构造函数内初始化
const int _n;
A _aa;
};