一、运算符重载引入
#include<iostream>
using namespace std;
class Date
{
public:
//构造函数
Date(int year=1999,int month=11,int day=23)
{
_year = year;
_month = month;
_day = day;
}
int _year;
int _month;
int _day;
};
//重载运算符 == (重载为全局函数)
bool operator==(const Date& d1, const Date& d2)
{
return d1._day == d2._day &&
d1._month == d2._month &&
d1._year == d2._year;
}
int main()
{
Date d1(2003, 6, 21);
Date d2(2004, 12, 6);
if (d1 == d2)
{
cout << "d1==d2" << endl;
}
else
{
cout << "d1!=d2" << endl;
}
return 0;
}
根据这个例子,判断d1对象和d2对象是否相同,我们可以将 == 重载为全局函数,但此时必须要求类中的数据变量时公有成员
对于这种情况,我们可以将运算符重载为类的成员函数(这种方法在之后的学习中使用最多)
#include<iostream>
using namespace std;
class Date
{
public:
Date(int year=1999,int month=11,int day=23)
{
_year = year;
_month = month;
_day = day;
}
bool operator==(const Date& d)
{
return _day == d._day &&
_month == d._month &&
_year == d._year;
//也可以写为
/*return this->_day == d._day &&
this->_month == d._month &&
this->_year == d._year;*/
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1(2003, 6, 21);
Date d2(2004, 12, 6);
if (d1 == d2)
{
cout << "d1==d2" << endl;
}
else
{
cout << "d1!=d2" << endl;
}
return 0;
}
对比这俩种重载的情况,我们可以发现,他们的参数数目不同,这也是他们之间的一个区别
1.将运算符重载为全局函数时,根据该运算符的自身情况(单目或者双目),来决定参数的个数,单目运算符需要一个操作数,则参数为一个;双目运算符需要两个操作数,则参数需要两个
2.将运算符重载为类的成员函数时,参数个数等于运算符的目数减一 (因为类的成员函数中隐含一个this指针)
二、赋值运算符(重点)
赋值运算符(=)只能重载为 类的成员函数 不能重载为全局函数
我们发现编译报错,为什么会出现这种情况呢?
答:赋值运算符如果不显式实现,编译器会生成一个默认的(简单说,就是赋值运算符可以不被重载,编译器会在我们用户没有写重载函数的情况下,自动生成一个默认的重载函数)此时用户再在类外自己实现一个全局的 赋值运算符重载,就和编译器在类中生成的默认赋值运算符重载冲突了,故赋值运算符重载只能是类的 成员函数。
其次,我们还得注意一个问题:
既然编译器都自动给我们生成一个默认的赋值运算符重载函数了,我们还需要自己实现吗?
答:当然需要,对于上面的Date类,其中没有涉及到内存资源的管理,所以并没有什么影响;但是
一旦涉及到资源管理,就必须要我们自己实现。(在后期会细讲)
所以对于上述代码我们可以将其修改为:
但是对于这个代码来说,可以实现d2=d1,即d1对d2的赋值,但如果将赋值语句改变为 d3=d2=d1,就会报错
对于d3=d2=d1这种赋值,由于上述我们在实现运算符重载的时候没有设置返回值,即当d1给d2付完值之后,没有任何东西返回,这时候在给d3赋值,就会出错,所以我们可以修改代码如下:
#include<iostream>
using namespace std;
class Date
{
public:
Date(int year=1999,int month=11,int day=23)
{
_year = year;
_month = month;
_day = day;
}
Date& operator=(Date& d)
{
d._year = _year;
d._month =_month;
d._day = _day;
return d;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1(2003, 6, 21);
Date d2;
Date d3;
d3 = d2 = d1;
return 0;
}
三、单目运算符重载
1.重载前置++
根据我们上述讲述,我们可以简单实现代码:
#include<iostream>
using namespace std;
class Date
{
public:
Date(int year=1999,int month=11,int day=23)
{
_year = year;
_month = month;
_day = day;
}
//重载前置++
Date& operator++()
{
_day++;
return *this;
}
void display()
{
cout << _year << "/" << _month << "/" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1(2003, 6, 21);
++d1;
d1.display();
return 0;
}
那么当我们要重载后置++时候,是不是和前置++一模一样了,答案当然是否定的,那怎么进行区别呢,对于重载后置++的函数,又该怎么样写呢?
C++对于这种这种情况,为了让前置++和后置++都可以实现重载,规定:后置++在重载的时候多增加一个int类型的参数,但调用该函数时候,该参数不传递,编译器自动传递
代码演示:
#include<iostream>
using namespace std;
class Date
{
public:
Date(int year=1999,int month=11,int day=23)
{
_year = year;
_month = month;
_day = day;
}
//重载前置++
Date& operator++()
{
_day++;
return *this;
}
//重载后置++
Date operator++(int)
{
Date temp(*this);
this->_day++;
return temp;
}
//重载赋值运算符 =
Date& operator=(Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
void display()
{
cout << _year << "/" << _month << "/" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1(2003, 6, 21);
++d1;
d1.display();
Date d2=d1++;
d2.display();
d1.display();
return 0;
}
运行结果:
对于上述代码还需要注意一个问题:
四、常见的运算符重载(简单日期类实现)
#include<iostream>
using namespace std;
class Date {
public:
// 获取某年某月的天数
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(int year = 1900, int month = 1, int day = 1)
:_year(year),
_month(month),
_day(day)
{
int m = GetMonthDay(_year, _month);
if (_year<=0||_month > 13 || _month<1 || _day<=0||_day>m)
{
cout << "构造日期不符合,默认构造日期为1900/1/1" << endl;
_year = 1900;
_month = 1;
_day = 1;
}
}
// 拷贝构造函数
// d2(d1)
Date(const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
// 赋值运算符重载
// d2 = d3 ------> d2.operator=(&d2, d3)
Date& operator=(const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
return *this;
}
// 析构函数
~Date()
{
cout << "~Date()" <<this<< endl;
}
// 日期+=天数
Date& operator+=(int day)
{
_day += day;
while (_day > GetMonthDay(_year, _month))
{
_day -= GetMonthDay(_year, _month);
_month += 1;
if (_month > 12)
{
_year += 1;
_month = 1;
}
}
return *this;
}
// 日期+天数
Date& operator+(int day)
{
//用(*this)拷贝构造一个对象temp
Date temp(*this);
temp._day += day;
//如果加完天数之后的结果比当前月份的天数大,说明不符合日期规则
//进行修改
while (temp._day >temp.GetMonthDay(temp._year, temp._month))
{
//1.将当前天天数 减去 当前月份的天数
temp._day -= temp.GetMonthDay(temp._year, temp._month);
//2.将当前月份加1
temp._month += 1;
//如果加1后月份的值大于12,不符合规则
//将当前年加1,当前月份变为1月,表示下一年的一月份
if (temp._month > 12)
{
temp._year += 1;
temp._month = 1;
}
}
return temp;
}
// 日期-天数
Date& operator-(int day)
{
//用(*this)拷贝构造一个对象temp
Date temp(*this);
temp._day -= day;
//2022年1月10号 - 20天
//如果减完天数后的值小于等于0,说明不符合日期规则
while (temp._day<=0)
{
//1.将当前月份减1
temp._month -= 1;
//如果当前月份减1后为0,不符合规则
//将当前年减1,月份值赋值为12,表示上一年的12月份
if (temp._month == 0)
{
temp._year -= 1;
temp._month = 12;
}
//3.将当前天数 + 当前月份的总天数
temp._day += temp.GetMonthDay(temp._year, temp._month);
}
return temp;
}
// 日期-=天数
Date& operator-=(int day)
{
_day -= day;
while (_day <= 0)
{
_month -= 1;
if (_month == 0)
{
_year -= 1;
_month = 12;
}
_day += GetMonthDay(this->_year, this->_month);
}
return *this;
}
// 前置++
Date& operator++()
{
_day += 1;
if (_day > GetMonthDay(_year, _month))
{
_day = 1;
_month += 1;
if (_month > 12)
{
_year++;
_month = 1;
}
}
return *this;
}
// 后置++
Date& operator++(int)
{
Date temp(*this);
_day++;
if (_day > GetMonthDay(_year, _month))
{
_day = 1;
_month += 1;
if (_month > 12)
{
_year++;
_month = 1;
}
}
return temp;
}
// 后置--
Date operator--(int)
{
Date temp(*this);
_day--;
if (_day<=0)
{
_month--;
if (_month == 0)
{
_month = 12;
_year--;
}
_day+=GetMonthDay(_year, _month);
}
return temp;
}
// 前置--
Date& operator--()
{
--_day;
if(_day <=0)
{
_month -= 1;
if (_month == 0)
{
_year--;
_month = 12;
}
_day += GetMonthDay(_year, _month);
}
return *this;
}
// >运算符重载
bool operator>(const Date& d)const
{
if (_year > d._year)
{
return true;
}
else if (_year == d._year && _month > d._month)
{
return true;
}
else if (_year == d._year && _month == d._month && _day > d._day)
{
return true;
}
return false;
}
// ==运算符重载
bool operator==(const Date& d)
{
if ((*this) != d)
{
if (this->_year == d._year &&
this->_month == d._month &&
this->_day == d._day)
{
return true;
}
else
{
return false;
}
}
return true;
}
// >=运算符重载
bool operator >= (const Date& d)const
{
if (_year > d._year)
{
return true;
}
else if (_year == d._year && _month > d._month)
{
return true;
}
else if (_year == d._year && _month == d._month && _day > d._day)
{
return true;
}
if (this->_year == d._year && this->_month == d._month && this->_day == d._day)
{
return true;
}
return false;
}
// <运算符重载
bool operator < (const Date& d)
{
if (_year < d._year)
{
return true;
}
else if (_year == d._year && _month < d._month)
{
return true;
}
else if (_year == d._year && _month == d._month && _day < d._day)
{
return true;
}
return false;
}
// <=运算符重载
bool operator <= (const Date& d)
{
if (_year < d._year)
{
return true;
}
else if (_year == d._year && _month < d._month)
{
return true;
}
else if (_year == d._year && _month == d._month && _day < d._day)
{
return true;
}
if (this->_year == d._year && this->_month == d._month && this->_day == d._day)
{
return true;
}
return false;
}
// !=运算符重载
bool operator != (const Date& d)
{
if (_year != d._year || _month != d._month || _day != d._day)
{
return true;
}
return false;
}
//友元函数重载输入输出
friend ostream& operator<<(ostream& cout, Date& d)
{
cout << d._year << "/" << d._month << "/"<<d._day;
return cout;
}
friend istream& operator>>(istream& cin, Date& d)
{
cin >> d._year >> d._month >> d._day;
return cin;
}
void Print()
{
cout << _year << "/" << _month << "/" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
void Test1()
{
Date d1;
cin >> d1;
Date d2;
cin >> d2;
cout << d1 << " " << d2 << endl;
d1 += 872;
d2 -= 900;
cout <<"d1=" << d1 <<" " << "d2=" << d2 << endl;
cout << "d1>d2: " << (d1 > d2)<< endl;
Date d3=d1++;
Date d4=--d2;
cout << "d3=" << d3 <<" "<<"d4="<<d4<< endl;
cout << "d3==d4: " << (d3 == d4) << endl;
cout << "d1=" << d1 << " " << "d2=" << d2 << endl;
cout << "d1!=d2: " << (d1 != d2) << endl;
}
int main()
{
Test1();
return 0;
}