运算符重载
C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。
函数名字为:关键字operator后面接需要重载的运算符符号。
函数原型:返回值类型 operator操作符(参数列表)。
注意:
1、不能通过连接其他符号来创建新的操作符:比如operator@
2、重载操作符必须有一个类类型或者枚举类型的操作数
3、用于内置类型的操作符,其含义不能改变,例如:内置的整型+,不 能改变其含义
4、作为类成员的重载函数时,其形参看起来比操作数数目少1成员函数的操作符有一个默认的形参this,限定为第一个形参
5、.* 、:: 、sizeof 、?: 、. 注意以上5个运算符不能重载。这个经常在笔试选择题中出现。
将‘重载“==”符号为成员函数///
class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
// bool operator==(Date* this, const Date& d2)
// 这里需要注意的是,左操作数是this指向的调用函数的对象
bool operator==(const Date& d2)
{
return _year == d2._year;
&& _month == d2._month
&& _day == d2._day;
}
private:
int _year;
int _month;
int _day;
};
void Test ()
{
Date d1(2018, 9, 26);
Date d2(2018, 9, 27);
cout<<(d1 == d2)<<endl;
}
当在我们尝试去重载operator<<,然后发现我们没办法将operator<<重载成成员函数。因为cout的输出流对象和隐含的this指针在抢占第一个参数的位置。this指针默认是第一个参数也就是左操作数了。但是实际使用中cout需要是第一个形参对象,才能正常使用。所以我们要将operator<<重载成全局函数。但是这样的话,又会导致类外没办法访问成员,那么这里就需要友元来解决。
插入:友元函数
友元函数:打破了安全性、封装性。
友元函数可以直接访问类的私有成员,它是定义在类外部的普通函数,不属于任何类,但需要在类内声明,声明时需要加friend关键字。
注意:
1、友元函数可访问类的私有和保护成员,但不是类的成员函数
2、友元函数不能用const修饰
3、友元函数可以在类定义的任何地方声明,不受类访问限定符限制
4、一个函数可以是多个类的友元函数
5、友元函数的调用与普通函数的调用和原理相同
class Date
{
friend ostream& operator<<(ostream& _cout, const Date& d);
public:
Date(int year, int month, int day)
: _year(year)
, _month(month)
, _day(day)
{}
private:
int _year;
int _month;
int _day;
};
ostream& operator<<(ostream& _cout, const Date& d)
{
_cout<<d._year<<"-"<<d._month<<"-"<<d._day;
return _cout;
}
int main()
{
Date d;
cin>>d;
cout<<d<<endl;
return 0;
}
实现日期类
日期类的成员数据
class Date{
private:
int _year;
int _month;
int _day;
};
全缺省的构造函数
使用参数列表对成员数据初始化,提高效率
Date(int year = 1900, int month = 1, int day = 1) :_year(year), _month(month), _day(day)
{}
全缺省的构造函数
Date& Date::operator++(){
_day++;
int days = GetMonthDay(_year, _month);
if (_day>days)
{
_day = 1;
_month++;
if (_month>12)
{
_month = 1;
_year++;
}
}
return *this;
}
拷贝构造函数
因为成员数据没有指针或者数组,所以用的是值拷贝(浅拷贝),否则必须为深拷贝。
Date::Date(const Date& d){
_year = d._year;
_month = d._month;
_day = d._day;
}
赋值运算符重载
Date& Date::operator=(const Date& d){
if (this!=&d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
return *this;
}
输出流<<重载
ostream& operator<<(ostream &out ,const Date& d){
out <<d._year<<"年"<<d._month<<"月"<<d._day<<"日";
return out;
}
判断是否为闰年
bool Date::IsLeap(int year){
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
获取某年某月的天数
int Date::GetMonthDay(int year, int month)
{
// 1 2 3 4 5 6 7 8 9 10 11 12
int arr[13] = { 29, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
if (month==2)
{
if (IsLeap(year))
{
return arr[0];
}
}
return arr[month];
}
获取星期
设置:2022年12月1日:星期四,为标准
int Date::Getweek(int year,int month ,int day){
// 0 1 2 3 4 5 6
char arr[7] = { 7, 1, 2, 3, 4, 5, 6 };
//char arr[8] = { "星期天","星期一","星期二" , "星期三", "星期四", "星期五", "星期六"};
int week = 0;
//2022年12月1日:星期四
Date std(2022, 12, 1);
Date d(year, month, day);
int n = 0;
if (std>d)
{n = -(std - d);}
else
{n = std -d;}
int m = 4 + n;
if (m<0)
{m = -m;}
if (std>d)
{
if ((-n)<4)
{
week =4+n;
}
else{
week = ((7 - (m % 7)) % 7);
}
}
else
{week = m % 7;}
return arr[week];
}
重载日期+天数
Date Date::operator+(int n)
{
int year = _year, month = _month, day = _day;
int days = GetMonthDay(year, month);
while ((day+n)>days)
{
month++;
n -=days;
if (month>12)
{
month = 1;
year++;
}
days=GetMonthDay(year, month);
}
day+= n;
return Date(year,month,day);
}
重载日期-天数
Date Date::operator-(int n){
int year = _year, month = _month, day = _day,a_month=_month-1;
int days;
if (a_month==0)
days = GetMonthDay(year, 12);
else
days = GetMonthDay(year,a_month);
while (n-day>0)
{
month--;
a_month--;
n -= days;
if (month==0)
{
year--;
month = 12;
a_month = month - 1;
}
if (a_month==0)
days = GetMonthDay(year, 12);
else
days = GetMonthDay(year,a_month);
}
day = day - n;
return Date(year, month, day);
}
重载日期,前++、后++、+=
//前++
Date& Date::operator++(){
_day++;
int days = GetMonthDay(_year, _month);
if (_day>days)
{
_day = 1;
_month++;
if (_month>12)
{
_month = 1;
_year++;
}
}
return *this;
}
//后++
Date Date::operator++(int){
Date tmp = *this;
*this += 1;
return tmp;
}
//+=
Date& Date::operator+=(int day){
Date t = *this + day;
//Date t = *(this + day);
*this = t;
return *this;
}
重载日期,前–、后–、-=
// 前置--
Date& Date::operator--(){
*this -= 1;
return *this;
}
//后置--
Date Date::operator--(int){
Date tmp = *this;
*this -= 1;
return tmp;
}
//-=
Date& Date::operator-=(int day){
Date tmp = *this - day;
*this = tmp;
return *this;
}
>、<=运算符重载`
//>
bool Date::operator>(const Date& d){
return(_year > d._year) ||
(_year == d._year&&_month > d._month) ||
(_year == d._year&&_month == d._month&&_day > d._day);
}
//<=
bool Date::operator<=(const Date& d) {
return !(*this > d);
}
<、>=运算符重载
//<
bool Date::operator<(const Date& d){
return(_year < d._year) ||
(_year == d._year&&_month < d._month) ||
(_year == d._year&&_month == d._month&&_day < d._day);
}
//>=
bool Date::operator>=(const Date& d) {
return !(*this < d);
}
==、!=运算符重载
//==
bool Date::operator==(const Date& d){
return (_year == d._year) && (_month == d._month) && (_day == d._day);
}
//!=
bool Date::operator!=(const Date& d){
return !(*this==d);
}
打印月历
void Date::printf_Month(int year, int month)
{
int n = Date::Getweek(year,month,1);
cout << " 星期天 " << " 星期一 " << " 星期二 " << " 星期三 " << " 星期四 " << " 星期五 " << " 星期六 " << endl;
if (n==7)
{
for (int i = 1; i < GetMonthDay(year, month) + 1; i++)
{
cout << " " << i << " ";
if ((i!=1)&&(Getweek(year, month,i) % 7==6))
{
cout << endl;
}
}
}
else
{
while (n)
{
cout << " " ;
n--;
}
n = Date::Getweek(year, month, 1);
for (int i = 1; i <GetMonthDay(year, month) + 1; i++)
{
cout << " " << i << " ";
if ((Getweek(year, month, i) % 7 )&& (Getweek(year, month, i) % 7 == 6))
{
cout << endl;
}
}
}
cout << endl;
}
日期-日期,返回天数
int Date::operator-(const Date& d){
int n=0;
int year = d._year, month = d._month, day = d._day;
if (*this == d) //判断是否为同一天
{
return 0;
}
if (*this>d) //q-p,判断q、p的大小,给日期小的加天数,先使day相等、后month相等、最后year相等
{
if (_day > day)
{
n = _day - day;
day = _day;
}
else
{
n = GetMonthDay(year,month) +_day - day;
day = _day;
month++;
if (month == 13)
{
year++;
month = 1;
}
}
while (_month!=month)
{
n = n + GetMonthDay(year, month);
month++;
if (month==13)
{
year++;
month = 1;
}
}
while (_year!=year)
{
if (IsLeap(year))
{
n = n + 366;
}
else
{
n = n + 365;
}
year++;
}
return n;
}
else //当q-p,p>q时
{
if (day > _day)
{
n = day - _day;
_day = day;
}
else
{
n = GetMonthDay(_year, _month) + day - _day;
_day = day;
_month++;
if (_month == 13)
{
_year++;
_month = 1;
}
}
while (month != _month)
{
n = n + GetMonthDay(_year, _month);
_month++;
if (_month == 13)
{
_year++;
_month = 1;
}
}
while (year !=_year)
{
if (IsLeap(_year))
{
n = n + 366;
}
else
{
n = n + 365;
}
_year++;
}
return n;
}
}
总代码
#include<iostream>
using namespace std;
class Date
{
friend ostream& operator<<(ostream &out, const Date& d);
public:
// 获取某年某月的天数
int GetMonthDay(int year, int month);
//获取星期
int Getweek(int year,int month,int day);
//打印月历
void printf_Month(int year, int month);
// 全缺省的构造函数
Date(int year = 1900, int month = 1, int day = 1) :_year(year), _month(month), _day(day)
{}
// 拷贝构造函数
// d2(d1)
Date(const Date& d);
// 赋值运算符重载
// d2 = d3 -> d2.operator=(&d2, d3)
Date& operator=(const Date& d);
// 析构函数
~Date()
{}
public:
// 日期+=天数
Date& operator+=(int day);
// 日期+天数
Date operator+(int day);
// 日期-天数
Date operator-(int day);
// 日期-=天数
Date& operator-=(int day);
public:
// 前置++
Date& operator++();
// 后置++
Date operator++(int);
// 后置--
Date operator--(int);
// 前置--
Date& operator--();
public:
// >运算符重载
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);
public:
// 日期-日期 返回天数
int operator-(const Date& d);
protected:
bool IsLeap(int year);
private:
int _year;
int _month;
int _day;
};
bool Date::IsLeap(int year){
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
int Date::GetMonthDay(int year, int month)
{
// 1 2 3 4 5 6 7 8 9 10 11 12
int arr[13] = { 29, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
if (month==2)
{
if (IsLeap(year))
{
return arr[0];
}
}
return arr[month];
}
//输出流重载
ostream& operator<<(ostream &out ,const Date& d){
out <<d._year<<"年"<<d._month<<"月"<<d._day<<"日";
return out;
}
Date::Date(const Date& d){
_year = d._year;
_month = d._month;
_day = d._day;
}
Date& Date::operator=(const Date& d){
if (this!=&d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
return *this;
}
bool Date::operator==(const Date& d){
return (_year == d._year) && (_month == d._month) && (_day == d._day);
}
// 日期+天数
Date Date::operator+(int n)
{
int year = _year, month = _month, day = _day;
int days = GetMonthDay(year, month);
while ((day+n)>days)
{
month++;
n -=days;
if (month>12)
{
month = 1;
year++;
}
days=GetMonthDay(year, month);
}
day+= n;
return Date(year,month,day);
}
Date Date::operator-(int n){
int year = _year, month = _month, day = _day,a_month=_month-1;
int days;
if (a_month==0)
days = GetMonthDay(year, 12);
else
days = GetMonthDay(year,a_month);
while (n-day>0)
{
month--;
a_month--;
n -= days;
if (month==0)
{
year--;
month = 12;
a_month = month - 1;
}
if (a_month==0)
days = GetMonthDay(year, 12);
else
days = GetMonthDay(year,a_month);
}
day = day - n;
return Date(year, month, day);
}
Date& Date::operator-=(int day){
Date tmp = *this - day;
*this = tmp;
return *this;
}
Date& Date::operator+=(int day){
Date t = *this + day;
//Date t = *(this + day);
*this = t;
return *this;
}
Date& Date::operator++(){
_day++;
int days = GetMonthDay(_year, _month);
if (_day>days)
{
_day = 1;
_month++;
if (_month>12)
{
_month = 1;
_year++;
}
}
return *this;
}
Date Date::operator++(int){
Date tmp = *this;
*this += 1;
return tmp;
}
Date Date::operator--(int){
Date tmp = *this;
*this -= 1;
return tmp;
}
// 前置--
Date& Date::operator--(){
*this -= 1;
return *this;
}
bool Date::operator>(const Date& d){
return(_year > d._year) ||
(_year == d._year&&_month > d._month) ||
(_year == d._year&&_month == d._month&&_day > d._day);
}
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(_year < d._year) ||
(_year == d._year&&_month < d._month) ||
(_year == d._year&&_month == d._month&&_day < d._day);
}
bool Date::operator>=(const Date& d) {
return !(*this < d);
}
int Date::operator-(const Date& d){
int n=0;
int year = d._year, month = d._month, day = d._day;
if (*this == d)
{
return 0;
}
if (*this>d)
{
if (_day > day)
{
n = _day - day;
day = _day;
}
else
{
n = GetMonthDay(year,month) +_day - day;
day = _day;
month++;
if (month == 13)
{
year++;
month = 1;
}
}
while (_month!=month)
{
n = n + GetMonthDay(year, month);
month++;
if (month==13)
{
year++;
month = 1;
}
}
while (_year!=year)
{
if (IsLeap(year))
{
n = n + 366;
}
else
{
n = n + 365;
}
year++;
}
return n;
}
else
{
if (day > _day)
{
n = day - _day;
_day = day;
}
else
{
n = GetMonthDay(_year, _month) + day - _day;
_day = day;
_month++;
if (_month == 13)
{
_year++;
_month = 1;
}
}
while (month != _month)
{
n = n + GetMonthDay(_year, _month);
_month++;
if (_month == 13)
{
_year++;
_month = 1;
}
}
while (year !=_year)
{
if (IsLeap(_year))
{
n = n + 366;
}
else
{
n = n + 365;
}
_year++;
}
return n;
}
}
int Date::Getweek(int year,int month ,int day){
// 0 1 2 3 4 5 6
char arr[7] = { 7, 1, 2, 3, 4, 5, 6 };
int week = 0;
//2022年12月1日:星期四
Date std(2022, 12, 1);
Date d(year, month, day);
int n = 0;
if (std>d)
{n = -(std - d);}
else
{n = std -d;}
int m = 4 + n;
if (m<0)
{m = -m;}
if (std>d)
{
if ((-n)<4)
{
week =4+n;
}
else{
week = ((7 - (m % 7)) % 7);
}
}
else
{week = m % 7;}
return arr[week];
}
void Date::printf_Month(int year, int month)
{
int n = Date::Getweek(year,month,1);
cout << " 星期天 " << " 星期一 " << " 星期二 " << " 星期三 " << " 星期四 " << " 星期五 " << " 星期六 " << endl;
if (n==7)
{
for (int i = 1; i < GetMonthDay(year, month) + 1; i++)
{
cout << " " << i << " ";
if ((i!=1)&&(Getweek(year, month,i) % 7==6))
{
cout << endl;
}
}
}
else
{
while (n)
{
cout << " " ;
n--;
}
n = Date::Getweek(year, month, 1);
for (int i = 1; i <GetMonthDay(year, month) + 1; i++)
{
cout << " " << i << " ";
if ((Getweek(year, month, i) % 7 )&& (Getweek(year, month, i) % 7 == 6))
{
cout << endl;
}
}
}
cout << endl;
}
void main(){
Date a(2024, 2, 20);
cout << "a : " << a << endl;
int days = a.GetMonthDay(2023, 2);
cout << "days = " << days << endl;
//拷贝构造
Date b = a;
cout << "b : " << b << endl;
//赋值语句
Date c;
c = a;
cout << "c : " << c << endl;
Date d(2022, 7, 12);
if (d > c)
{
cout << "d >c " << endl;
}
else
{
cout << " d<=c " << endl;
}
cout << "d : " << d << endl;
//Date e=d +30;
//cout <<"d : (+30)"<< d;
//cout <<"e : "<<e;
d += 1765;
cout << "d : (+=1765) " << d << endl;
Date f = d - 1765;
cout << "f : (d-1765)" << f << endl;
//前++
Date g(2000, 2, 28);
cout << "g = " << g<<endl;
++g;
cout << "++g= " << g<<endl;
//测试日期减日期
int n = d - f;
cout << "n = " << n << endl;
int n1 = f - d;
cout << "n1 = " << n1 << endl;
//测试给一个日期,得到星期
Date h(2022, 11, 12);
int week = h.Getweek(2022, 11, 12);
cout << h << "是星期" << week << endl;
//测试月历,以2022年为例
cout << " 2022年1月 " << endl << endl << endl;
h.printf_Month(2022, 1);
cout << endl << endl << endl << endl;
cout << " 2022年2月 " << endl << endl << endl;
h.printf_Month(2022, 2);
cout << endl << endl << endl << endl;
cout << " 2022年3月 " << endl << endl << endl;
h.printf_Month(2022, 3);
cout << endl << endl << endl << endl;
cout << " 2022年4月 " << endl << endl << endl;
h.printf_Month(2022, 4);
cout << endl << endl << endl << endl;
cout << " 2022年5月 " << endl << endl << endl;
h.printf_Month(2022, 5);
cout << endl << endl << endl << endl;
cout << " 2022年6月 " << endl << endl << endl;
h.printf_Month(2022, 6);
cout << endl << endl << endl << endl;
cout << " 2022年7月 " << endl << endl << endl;
h.printf_Month(2022, 7);
cout << endl << endl << endl << endl;
cout << " 2022年8月 " << endl << endl << endl;
h.printf_Month(2022, 8);
cout << endl << endl << endl << endl;
cout << " 2022年9月 " << endl << endl << endl;
h.printf_Month(2022, 9);
cout << endl << endl << endl << endl;
cout << " 2022年10月 " << endl << endl << endl;
h.printf_Month(2022, 10);
cout << endl << endl << endl << endl;
cout << " 2022年11月 " << endl << endl << endl;
h.printf_Month(2022, 11);
cout << endl << endl << endl << endl;
cout << " 2022年12月 " << endl << endl << endl;
h.printf_Month(2022, 12);
cout << endl << endl << endl << endl;
}
运行结果: