运算符重载
C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其
返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。运算符重载,就是让原本已经存在的运算符有了新的用法和意义。
比如我们熟知的减号 ( - ),原本是用来进行数字的相减处理。但经过运算符重载后,它可以用来进行其他类型的相减,像时间类相减、日期类相减、字符类相减等。
运算符重载一般是作为类的成员函数出现。当我们需要运算符重载时,往往是类中一种特殊的类型需要处理或者类本身需要处理。就像我们可能会把时间作为一个类,里面有小时、分钟、秒。如果让时间相减,那么减号的参数类型就变成了时间类。因此,重载作为类的成员函数出现,减少在我们调用运算符重载时发生冲突的可能。
函数名为:关键字operator后面接需要重载的运算符符号。
具体格式:[返回值] operator[运算符] (参数…) { … };
例:
bool operator==(const Date& d2)
{
return _year == d2._year && _month == d2._month && _day == d2._day;
}
注意:
- 不能通过连接其他符号来创建新的操作符:比如operator@
- 重载操作符必须有一个类类型参数
- 用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不 能改变其含义
- 作为类成员函数重载时,其形参比操作数数目少1,因为成员函数的第一个参数为隐藏的this
- ( .* )、 ( :: ) 、( . )、 (?:)这四个运算符不能够被重载
- ( = )、( [ ] )、( () )、( -> )只能重载为成员函数
日期类的定义
注意:后续运算符重载代码示例以日期类为例
class Date
{
private:
int _year;
int _month;
int _day;
public:
Date(int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
};
赋值运算符重载
所谓赋值运算符也就是”=“,对于内置类型我们可以直接使用等号来进行赋值,但是类对象就不行。因此我们对于赋值运算符进行重载,而后就可以使用一个定义好的类对象对于另一个类对象进行赋值。
这里的实现也没有很难,就是进行值的传递,然后返回接收好数据的对象即可。这里赋值的发出者没有进行改变,所以我们选择用const进行修饰;返回后的*this对象并没有被释放掉,所以我们选择返回引用来减少拷贝。
代码实现:
Date& Date::operator=(const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
return *this;
}
+= 重载
要实现日期类的相加相减,我们需要一个函数来求当月的最大天数,这里定义一个GetMonthday( ) 函数
int Date::GetMonthDay(int year, int month)
{
static int day_num[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_num[month];
}
}
这里实现日期类的相加
Date& Date::operator+=(int day)
{
_day += day;
while (_day > GetMonthDay(_year, _month))
{
_day -= GetMonthDay(_year, _month);
_month++;
if (_month == 13)
{
_year++;
_month = 1;
}
}
return *this;
}
日期类的相加需要处理进位问题,day 超过当月上限要进位,月超过13要进位,所以需要特定的函数去实现求每个月有多少天。否则在每个运载符重载函数中就都需要去求当月的最大天数,这无疑会造成代码的冗余。
之后日期类的相加就只要控制好什么时候需要进位即可
-=重载
思路与 += 运算类似,不再过多阐述
Date& Date::operator-=(int day)
{
_day -= day;
while (_day <= 0)
{
_month--;
if (_month <= 0)
{
_month = 12;
_year--;
}
_day += GetMonthDay(_year, _month);
}
return *this;
}
+重载
Date Date::operator+(int day)
{
*this += day;
return *this;
}
这里思路很简单,只需要复用+=运算即可,并且直接对 *this 进行操作
-重载
Date Date::operator-(int day) const
{
*this -= day;
return *this;
}
前置++ & 后置++
定义日期类,以日期类为例子
前置++
前置++:返回+1之后的结果
注意:this指向的对象函数结束后不会销毁,故以引用方式返回提高效率
Date& operator++()
{
_day += 1;
return *this;
}
后置++:
前置++和后置++都是一元运算符,为了让前置++与后置++形成能正确重载
C++规定:后置++重载时多增加一个int类型的参数( 称为哑元 ),但调用函数时该参数不用传递,编译器
Date operator++(int)
{
Date temp(*this);
_day += 1;
return temp;
}
==重载
bool Date::operator==(const Date& d) const
{
return this->_year == d._year && this->_month == d._month && this->_day == d._day;
}
运算符重载
bool Date::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 Date::operator>=(const Date& d) const
{
return *this > d || *this == d;
}
<重载
bool Date::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 Date::operator <= (const Date& d) const
{
return *this < d || *this == d;
}
!=重载
bool Date::operator != (const Date& d) const
{
return !(*this == d);
}