操作符重载的实质是函数重载,C++预定义的操作符的操作对象只能是基本的数据类型,而对于我们用户自定义的类型如类类型也需要类似的运算操作,此时就需要重新定义这些这些运算符,赋予他们新功能,使他在特定的时候执行特定的操作,可以提高代码的可读性。
它的一般格式为:
返回值类型 oprerator<运算符>(参数列表)
{
//函数体
}
并不是所有的运算符都能重载
不能重载的运算符有:
. 成员选择符
.* 成员对象选择符
:: 作用域解析符
?: 三目运算符
sizeof()运算符
定义运算符重载函数时要注意:
- 重载运算符必须有一个类类型或枚举类型的操作数
- 不能更改原运算符的含义
- 做为成员函数时,参数比操作数数目少一,因为有一个隐含this指针
一般将赋值运算符定义为类的成员函数,算术运算符定义为非类成员函数
赋值运算符注意几点:
1.参数最好传引用(const修饰),可以少创建一个临时变量
2.返回值也返回引用,返回值的生命周期比函数要长
返回值不能为空,有可能还会连续赋值
3.一定要检查是否是自己给自己赋值,因为接下来的操作可能会释放空间,程序出错。
赋值运算符函数若未显示定义,系统会自动合成一个默认的赋值运算符函数,一般情况下都可以使用,但在有些情况下会出错,只要涉及资源,采用系统提供的就会有问题。
即所谓的深浅拷贝若为普通函数时,一般定义为类的友元
- ==和!=一般成对重载
- 重载 []时,一般定义两个,const和非const的,返回值为引用(若返回的是指,临时变量无名字具有常性,不能做左值)
- 解引用操作符和->操作符无参
前置++/– 必须返回原对象的引用,
后置++/–以值的形式返回,返回旧值
两个形成重载,后置++/–在传参时多传一个int,用来区分输入操作符>>和输出操作符<<必须定义为类的友元函数
class A
{
void operator<<(ostream& _cout)
{
//……
}
};
A a;
cout<<a; //左右操作数不对应,错误
a<<cout; //这样可以,但是不符合常逻辑
所有他们一般不重载成类的成员函数
若将其定义成普通函数
void operator<<(ostream& _cout,const A& a)
{
//……
}
无法访问类中的私有成员,需要类本身提供接口才可以
最好的方式是声明成类的友元函数,可以访问类中的私有成员
还有一点要注意:
返回值写成输出流的引用ostream&,才能支持连续输出