对于基本的数据类型,C++提供来许多预先定义的运算符,如“+,-,*,/”等,他们的运用大家应该已经很熟悉了。那么我们引入运算符重载的概念到底是为什么,比如是我们的加号可以完成基本数据类型的相加,那么我们想进行两个类的相加是否可以,带着这个疑问,我们验证一下。
在C++中引入运算符重载,就是为了解决不是基本类型的 运算,比如说类的相加。
下面我们来编写运算符重载函数来实现类的相加。
在使用的时候可以显示使用,也可以隐式的使用,都是正确的
C++运算符重载的规则:
1)C++中绝大部分的运算符允许重载,不能重载的运算符只有以下几个:
. 成员访问运算符
.* 成员指针访问运算符
:: 作用域运算符
sizeof 长度运算符
?: 条件运算符
2)C++语言只能对已有的C++运算符进行重载,不允许用户自定义新的运算符。
3)运算符重载是针对新类型数据的实际需求,对原有运算符进行适当的改造完成的。一般来讲,重载的功能应当与原有的功能相似(如用“+”实现加法,用“-”实现减法)。
4)重载不能改变运算符的操作对象(即操作数)的个数。
5)运算符重载函数的参数至少应有一个类对象(或类对象的引用)
我们的运算符重载函数至少有一个类对像
6)重载不能改变原有的运算符的优先级.
7)运算符重载函数可以是普通成员,也可以是类的成员函数,还可以是类的友元函数。
8)一般而言,用于类对象的运算符必须重载,但是赋值运算符“=”例外,不需要重载。
友元运算符重载函数
友元函数的概念:
当我们类的数据成员声明为私有时,我们定义普通的运算符重载函数重载类的运算符,我们在类外不能访问私有成员,我们对象的数据就不能修改了,我们访问类的私有成员就会报错。
为了解决这个问题,我们可以讲重载函数定义为友元函数,友元函数的形参为类的对象时,我们可以访问到,所以,我们讲重载函数声明为类的友元函数就可以了。
1)运算符重载函数operator@可以返回任何类型,甚至可以是void类型,但通常返回类型与它所操作的类型相同,这样可以使重载运算符用在复杂的表达式中。
2)有的运算符不能定义为友元运算符的重载函数,如赋值运算符“=”,下标运算符“[]”,函数调用运算符“()”等。
成员运算符重载函数
在C++中,可以把运算符重载函数定义成某个类的成员函数,称为成员运算符重载函数。
在成员运算符重载函数的形参列表中,若运算符是单目的,则参数表为空的;若运算符是双目的,则参数表中只有一个操作数;与普通重载函数,友元重载函数相比成员重载函数的形参少一个,因为成员函数的类可以访问直接,所以就少一个参数。
成员运算符重载函数与友元运算符重载函数的比较
1)对于双目运算符来说,成员运算符重载函数只有一个参数,而友元运算符重载函数只有一个参数。友元运算符重载函数的参数个数与操作数的个数相同,成员运算符重载函数的参数个数比操作数少一个。
2)双目运算符重载函数一般定义为友元运算符重载函数。
3)成员运算符重载函数和友元运算符重载函数都可以用习惯方式调用,也可以用他们的专用方式调用。
4)C++大部分运算符即可说明为成员运算符重载函数,又可以说明为友元运算符重载函数
单目运算符++和--的重载
在C++中,可以通过在运算符重载函数参数中是否插入关键字int 来区分前置++与后置++
前置++形参没有int,后置++形参多了int
赋值运算符=的重载
对于任一类X,如果没有用户自定义的赋值运算符函数,那么系统自动为其生成一个缺省的赋值运算符函数,定义类X中的成员到成员的赋值,例如:
X &operator=(const X& source)
{
成员间的赋值
}
如果没有用户自定义的赋值运算符函数,那么系统自动调用缺省的赋值运算符函数,进行内容的逐一赋值。
1.指针悬挂问题
在某些特性情况下,如类中有指针类型时,使用默认的赋值运算符函数会产生错误。
分析:
用深度复制解决指针悬挂问题
使用用户自定义的运算符重载函数。
下标运算符[]的重载可以解决数组越界等问题。