赋值运算符重载:
C++
为了增强代码的可读性引入了运算符重载
,
运算符重载是具有特殊函数名的函数
,也具有其返回值类
型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。
函数名字为:关键字
operator
后面接需要重载的运算符符号
。
函数原型:
返回值类型
operator
操作符
(
参数列表
)
注意:
不能通过连接其他符号来创建新的操作符:比如
operator@
重载操作符必须有一个类类型参数
用于内置类型的运算符,其含义不能改变,例如:内置的整型
+
,不 能改变其含义
作为类成员函数重载时,其形参看起来比操作数数目少
1
,因为成员函数的第一个参数为隐藏的
this
.* :: sizeof ?: .
注意以上
5
个运算符不能重载。这个经常在笔试选择题中出现。
看个例子
#include<iostream>
using namespace std;
class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
int _year;
int _month;
int _day;
};
// 这里会发现运算符重载成全局的就需要成员变量是公有的,那么问题来了,封装性如何保证?
// 这里其实可以用我们后面学习的友元解决,或者干脆重载成成员函数。
bool operator==(const Date& d1, const Date& d2) {
return d1._year == d2._year
&& d1._month == d2._month
&& d1._day == d2._day;
}
int main ()
{
Date d1(2018, 9, 26);//正常运行
Date d2(2018, 9, 27);//正常运行
cout<<(d1 == d2)<<endl;
}
上面的一般不用,下面是一般用的,是经典的赋值运算符重载。说明一下,这里的*this就是调用的主体本身。比如d1.operator(d2),那么*this和d1是一样的
#include<iostream>
using namespace std;
class Date
{
public:
Date(int year = 1, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
Date(const Date& d)
{
cout << "Date(const Date& d)" << endl;
_year = d._year;
_month = d._month;
_day = d._day;
}
void Print()
{
cout << _year << "-" << _month << "-" << _day << endl;
}
bool operator<(const Date& x)
{
if (_year < x._year)
{
return true;
}
else if (_year == x._year && _month < x._month)
{
return true;
}
else if (_year == x._year && _month == x._month && _day < x._day)
{
return true;
}
return false;
}
Date& operator=(const Date & d)
{
if (this != &d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
return *this;
}
/*
void operator=(const Date & d)//就上面这个赋值运算符而言,改成这样也是可以的
{
if (this != &d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
}
*/
private:
int _year;
int _month;
int _day;
};
int main() {
Date d1(2023,2,3);
Date d2;
Date d3(2024,5,6);
d2.operator=(d1);
d2.Print();//2023-2-3
cout<<d1.operator<(d3)<<endl;//输出1
cout<<(d1<d3)<<endl;//输出1.和上面那种写法是一样的,把operator关键区省去,只留下运算符
return 0;
}
然后区分一下两个东西,类Date还是用的上面这个
Date d1(2023,2,3);
Date d2(2024,5,6);
// 用一个已经存在的对象初始化另一个对象 -- 构造拷贝函数
Date d4 = d2; // 等价于 Date d4(d2);
//已经存在的两个对象之间复制拷贝 -- 运算符重载函数
d4 = d1;
当然,我们可以在运算符重载函数里面相互调用别的运算符重载函数,看个例子
bool Date::operator<(const Date& x)
{
if (_year < x._year)
{
return true;
}
else if (_year == x._year && _month < x._month)
{
return true;
}
else if (_year == x._year && _month == x._month && _day < x._day)
{
return true;
}
return false;
}
bool Date::operator==(const Date& x)
{
return _year == x._year
&& _month == x._month
&& _day == x._day;
}
// 复用
// d1 <= d2
bool Date::operator<=(const Date& x)
{
return *this < x || *this == x;
}
bool Date::operator>(const Date& x)
{
return !(*this <= x);
}
bool Date::operator>=(const Date & x)
{
return !(*this < x);
}
bool Date::operator!=(const Date& x)
{
return !(*this == x);
}
最后看一个日期类的综合运用
int Date::GetMonthDay(int year, int month)
{
static int daysArr[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
//if (((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) && month == 2)
if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
{
return 29;
}
else
{
return daysArr[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;
}
// d1 + 100
Date Date::operator+(int day)
{
Date tmp(*this);
tmp += day;
return tmp;
/*tmp._day += day;
while (tmp._day > GetMonthDay(tmp._year, tmp._month))
{
tmp._day -= GetMonthDay(tmp._year, tmp._month);
++tmp._month;
if (tmp._month == 13)
{
++tmp._year;
tmp._month = 1;
}
}
return tmp;
*/
}
// 前置++
Date& Date::operator++()
{
*this += 1;
return *this;
}
// 后置++
// 增加这个int参数不是为了接收具体的值,仅仅是占位,跟前置++构成重载
Date Date::operator++(int)
{
Date tmp = *this;
*this += 1;
return tmp;
}
int main(){
Date d1(2023, 4, 26);
// 都要++,前置++返回++以后的对象,后置++返回++之前的对象
++d1; // d1.operator++()
d1++; // d1.operator++(0)
}