🌟个人主页:落叶
🌟当前专栏: C++专栏
目录
赋值运算符重载
运算符重载
- 当运算符被⽤于类类型的对象时,C++语⾔允许我们通过运算符重载的形式指定新的含义。C++规定类类型对象使⽤运算符时,必须转换成调⽤对应运算符重载,若没有对应的运算符重载,则会编译报错。
- 运算符重载是具有特殊名字的函数,他的名字是由operator和后⾯要定义的运算符共同构成。和其他函数⼀样,它也具有其返回类型和参数列表以及函数体。
- 重载运算符函数的参数个数和该运算符作⽤的运算对象数量⼀样多。⼀元运算符有⼀个参数( 如:*/++/-- ),⼆元运算符有两个参数 (如: +/- />/<) ,⼆元运算符的左侧运算对象传给第⼀个参数,右侧运算对象传给第⼆个参数。
- 如果⼀个重载运算符函数是成员函数,则它的第⼀个运算对象默认传给隐式的this指针,因此运算符重载作为成员函数时,参数⽐运算对象少⼀个。
- 运算符重载以后,其优先级和结合性与对应的内置类型运算符保持⼀致。
- 不能通过连接语法中没有的符号来创建新的操作符:⽐如operator@。
- .* :: sizeof ?: . ? 注意以上5个运算符不能重载。(选择题⾥⾯常考,⼤家要记下)
- 重载操作符⾄少有⼀个类类型参数,不能通过运算符重载改变内置类型对象的含义,如: int operator+(int x, int y)
⼀个类需要重载哪些运算符,是看哪些运算符重载后有意义,⽐如Date类(日期类)重载operator-就有意义,日期减去日期可以得到还剩下但是天。
但是重载operator*就没有意义。
- 重载++运算符时,有前置++和后置++,运算符重载函数名都是operator++,⽆法很好的区分。C++规定,后置++重载时,增加⼀个int形参,跟前置++构成函数重载,⽅便区分。
- 重载<<和>>时,需要重载为全局函数,因为重载为成员函数,this指针默认抢占了第⼀个形参位置,第⼀个形参位置是左侧运算对象,调⽤时就变成了 对象<<cout,不符合使⽤习惯和可读性。重载为全局函数把ostream/istream放到第⼀个形参位置就可以了,第⼆个形参位置当类类型对象。
内置类型(int...)这些支持编译器自带的运算符,但是自定义类型(类类型...)这些,就不支持运算符了。
自定义类型,编译器不知道我们定义的自定义类型是什么要干什么。
所以编译器让我们自己根据自定义类型来实现运算符重载。
下面那个代码是比较2个日期类大小,用运算符重载函数(operator和运算符结合)来进行比较。
重载操作符⾄少有⼀个类类型参数,不能通过运算符重载改变内置类型对象的含义,如: int operator+(int x, int y)
重载运算符函数的参数个数和该运算符作⽤的运算对象数量⼀样多。⼀元运算符有⼀个参数( 如:*/++/-- ),⼆元运算符有两个参数 (如: +/- />/<) ,⼆元运算符的左侧运算对象传给第⼀个参数,右侧运算对象传给第⼆个参数。
下面这个代码私有的成员变量,不能被修改,所以会报错,公有就不会报错,也可以重载为成员函数。
#include<iostream>
using namespace std;
class Date
{
public://公有
//全缺省构造函数
Date(int year = 1, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
private:私有
//成员变量
int _year;//年
int _month;//月
int _day;//日
};
//--------------------------------------------------------------------
bool operator<(const Date& x1, const Date& x2)
{
//比较年
if (x1._year < x2._year)
{
return true;
}
//年相等,比较月
else if (x1._year == x2._year && x1._month < x2._month)
{
return true;
}
//年相等,月相等,比较日
else if (x1._year == x2._year && x1._month == x2._month && x1._day < x2._day)
{
return true;
}
//都等于,或大于返回false
return false;
}
int main()
{
Date d1(2024, 9, 2);
Date d2(2024, 7, 4);
//比较,结果给tab
bool tab2 = operator<(d1, d2);
//这样写,编译器会自动转换成operator<(d1, d2),所以这样写比较方便
bool tab = d1 < d2;
cout << tab << endl;
return 0;
}
重载为成员函数
重载为成员函数,就不能向上面这样写了。
我们可以看到下面报错了很多。运算符函数参数太多。
如果⼀个重载运算符函数是成员函数,则它的第⼀个运算对象默认传给隐式的this指针,因此运算符重载作为成员函数时,参数⽐运算对象少⼀个。
有隐式的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;
}
//不用写第一个参数,第一个参数有隐式的this指针
bool operator<( const Date& x2)
{
//比较年
if (_year < x2._year)
{
return true;
}
//年相等,比较月
else if (_year == x2._year && _month < x2._month)
{
return true;
}
//年相等,月相等,比较日
else if (_year == x2._year && _month == x2._month && _day < x2._day)
{
return true;
}
//都等于,或大于返回false
return false;
}
private:
int _year;//年
int _month;//月
int _day;//日
};
int main()
{
Date d1(2024, 9, 2);
Date d2(2024, 7, 4);
//比较,结果给tab
bool tab2 = d1.operator<(d2);
//这样写编译器会转换成 d1.operator<(d2), 所以这样写比较方便
bool tab = d1 < d2;
cout << tab << endl;
return 0;
}
这个d1类里的operator<函数,把d2传过去,这样就可以对2个类进行比较了。
也可以这样写。
//这样写编译器会转换成 d1.operator<(d2), 所以这样写比较方便
bool tab = d1 < d2;
我们可以看到它们在汇编,都是一样的。
.* :: sizeof ?: . ? 注意以上5个运算符不能重载。(选择题⾥⾯常考,⼤家要记下)。
class A
{
public:
//成员函数
void func()
{
cout << "A::func()" << endl;
}
};
typedef void(A::* PF)(); //成员函数指针类型
int main()
{
// C++规定成员函数要加&才能取到函数指针
PF pf = &A::func;
A obj; //定义ob类对象temp
// 对象调⽤成员函数指针时,使⽤.*运算符
(obj.*pf)();
return 0;
}
重载操作符⾄少有⼀个类类型参数,不能通过运算符重载改变内置类型对象的含义,如: int operator+(int x, int y)
// 编译报错:“operator +”必须⾄少有⼀个类类型的形参
int operator+(int x, int y)
{
return x - y;
}
重载++运算符时,有前置++和后置++,运算符重载