运算符重载规则
1.被重载的运算符必须是已经存在的C++运算符,不能重载自己创建的运算符;
2.运算符被重载之后,原有功能仍然保留。只是扩展了原有功能;
3.重载不能改变运算符运算对象的个数。+运算符具有两个操作数,在+运算符函数作为CTime的成员函数的时候,有一个参数是隐含的,也就是当前的对象,使用this来引用。另一个参数通过函数参数指定。
运算符关于重载
1.可以重载的运算符
1)算术运算符:+,-,*,/,%,
2)逻辑运算符:&&,||,!
3)关系运算符:>,<,=,>=,<=,==,!=
4)位操作符:~,<<,>>,&,^),|
5)自增自减运算符:++,--
自增和自减都有前后之分,所以++和—都有两种重载方式。
6)复合赋值运算符:+=,-=,*=,/=,%=
7)其他:&、*、()、->、[]、.new/delete、>>、<<
2.不能重载的运算符
?: . * :: sizeof(这也是一个运算符)
3.不需要重载的运算符
=(赋值)和&(取地址符)
1)在我们声明一个类的时候,系统也会为我们的类声明一个赋值运算符的重载,我们可以使用=使两个对象的所有数据成员相等。如果我们希望不用默认的方式赋值,对赋值有其它的操作,我们也可以对赋值运算符重载。如下:
成员函数的=运算符重载
CTime& CTime::operator=(CTime& time)
{
if(this == &time) //检查自赋值,判断左右操作数是否是同一个对象,避免不必要的赋值
{
return *this;
}
m_nHour = time.m_nHour; //我们在赋值函数里面采用了默认的操作,分别为它们的数据成员赋值
m_nMinute = time.m_nMinute;
m_nSecond = time.m_nSecond;
return *this; //为什么是返回一个引用呐?我们后面会再讲到。
}
如此我们两个对象间的赋值操作就可以自动调用这个赋值函数了。如果我们使用time=time进行赋值,我们通过调试可以看到在进行自赋值检查的时候,它不符合赋值的条件直接就返回了,这符合我们的想法。
还有一个问题:下面这个语句调用拷贝构造函数还是赋值函数呐?
CTime time=time1;//它调用的是拷贝构造函数,因为语句面临的是一个对象的创建,而赋值函数只是在已有的对象进行赋值的时候才会调用,如下面语句:
CTime time;//调用无参的默认构造函数
time=time1;//调用赋值运算符,不会调用拷贝构造函数
判断运算符重载为成员函数还是友元函数
普通函数和类的成员函数都可以作为类的友元,但什么时候应该使用普通函数,什么时候应该使用成员函数方式呢?
普通函数形式的运算符函数一般都声明为类的友元函数,用以访问类的私有数据成员。这样可以减低开销,但破坏封装性。因此建议尽量使用成员函数形式。一般将单目运算符重载为成员函数,将双目运算符重载为友元函数。这只是一个建议,一个约定俗成的方法,你也可以根据自己的喜好来定义。
成员函数方式要求左侧的参数要与类类型相同。而普通函数则要求实参顺序与形参类型顺序一致。
1.有的运算符必须定义为类的成员函数:=、[]、()
2.有的运算符不能定义为类的成员函数,只能定义为类的友元:<<、>>
运算符重载可以执行任意的操作,因为你可以在函数体里面任意修改它的操作。比如可以将+定义成两个对象相减的操作,但是这样违背我们日常使用的习惯,容易使用误用,减低程序可读性,因此必须保证重载的运算符与该运算符应用于标准数据类型时所具有的功能。