一.运算符重载基础
1.1 运算符重载的概念
运算符重载,就是赋予运算符新的含义。函数重载就是对一个已有的函数赋予新的含义,使之实现新功能,即”一名多用”,运算符重载也是相同的道理。
运算符重载有很多常见的应用,如加法运算符 ”+ ”对可以对整数、单精度数和双精度数进行加法运算,如5+8, 5.8 +3.67等,但是计算机底层对整数、单精度数和双精度数据的加法操作过程是很不相同的, 但C++对运算符”+ ”进行了重载,所以”+ ”能适用于int, float, doUble类型的混合运算。
1.2 一个运算符重载的例子:
Complex是用户自己定义的一种数据类型
现在要实现Complex c3 = c1 + c2;
的操作,由于Complex是用户自定义类型,编译器根本不知道如何进行加减,只能使用函数实现相加功能,但是,C++提供了提供了一种机制,则可以实现使用“+”完成自定义类型相加的功能,这种机制就是运算符重载机制
//myAdd方式,可以实现两个Complex类型的数据相加的功能
Complex myAdd(Complex &c1, Complex &c2){
Complex tmp(c1.a+ c2.a, c1.b + c2.b);
return tmp;
}
//运算符重载
Complex operator+(Complex &c1, Complex &c2){
Complex tmp(c1.a+ c2.a, c1.b + c2.b);
return tmp;
}
在mian函数中,下面3条语句的能够实现相同的功能
Complex c3 = myAdd(c1, c2);
Complex c3 = operator+(c1, c2);
Complex c3 = c1 + c2;
1.3 运算符重载的本质:
根据上例可以看出:操作符重载的本质是通过函数扩展操作符的语义。
这个用来扩展操作符语义的函数被称为运算符重载函数,一个运算符被重载后,原有意义没有失去,只是定义了相对某一特定类的一个新运算符
1.4 运算符重载的限制条件:
1)不是所有运算符都是可以重载的,部分运算符不能重载
2)不能改变运算符的优先级
3)不能改变运算符的结核性
4)不能改变运算符所需要的操作数
5)不能创建新的运算符
二.运算符重载的使用
2.1 运算符重载的两种方式
对运算符进行重载时,一般有两种选择,可以使用成员函数或者非成员函数进行重载,这个非成员函数一般是友元函数,因为非成员函数中只有友元函数能访问类的私有数据,若进行运算符重载时使用到了类的私有数据,则只能用友元函数或成员函数
例如:对Complex类进行“+”运算符重载:
//方式一:使用友元函数
friend Complex operator+(Complex &c1, Complex &c2)
//方式二:使用成员函数
Complex operator-(Complex &c2)
友元函数进行运算符重载时所需的形参的数目与运算符使用的操作数数目相同,成员函数进行重载时则比友元函数重载少一个参数,原因是其中一个参数是被隐式地传递的调用对象
使用友元函数和成员函数进行重载的区别:
成员函数有this指针,所以成员函数可以隐式地传递参数,从而使参数比友元重载函数参数少一个。两种实现方式传递参数的方式不同,实现代码不同,应用场合也不同,但是达到的效果相同。
2.2 重载双目运算符:
注:下文使用op指代运算符
双目运算符:Object1 op Object2
方式一:成员函数
重载后调用方式实质:Object1.operator op(Object2 )
左参数由Object1对象通过this指针传递,右参数由参数Object2 对象传递
方式二:友元函数
重载后调用方式实质:operator op(Object1 ,Object2 )
左右参数由对象Object1和Object2传递
例子:对Complex类进行“+”运算符重载
//方式一:声明为成员函数
Complex operator+(Complex &c2)
//使用重载,两种方式等价
Complex c3 = c1.operator+(c2);
Complex c3 = c1 + c2;
//方式二:声明为友元函数
friend Complex operator+(Complex &c1, Complex &c2)
//使用重载,两种方式等价
Complex c3 = operator+(c1, c2);
Complex c3 = c1 + c2;
2.2 重载单目运算符:
单目运算符中,有一些运算符当位置不同时其含义不同,如“++”运算符和“–”运算符,i++表示先调用i然后i自增,++i表示i先自增然后再被调用。而其他运算符则没用这样的特性,如“.”运算符和“&”运算符
C++中通过占位参数来区分前置运算和后置运算
2.2.1 对位置固定的单目运算符的重载:
单目运算符:Object op 或 op Object
方式一:成员函数
重载后调用方式实质:Object.operator op( )
参数由Object对象通过this指针传递
方式二:友元函数
重载后调用方式实质:operator op(Object)
参数由对象Object传递
例子:对Complex类进行“&”运算符重载
//方式一:声明为成员函数
Complex operator&()
//使用重载,两种方式等价
Complex c3 = c1.operator&();
Complex c3 = &c1;
//方式二:声明为友元函数
friend Complex operator+(Complex &c1)
//使用重载,两种方式等价
Complex c3 = operator&(c1);
Complex c3 = &c1;
2.2.2 对位置不固定的单目运算符的重载:
运算符前置:op Objects
- | 成员函数 | 友元函数 |
---|---|---|
重载函数声明 | Objects : : Objects operator op( ) | Objects : : Objects operator op(Object &) |
调用方式实质 | Object.operator op( ) | operator op(Object) |
运算符后置:Objects op
运算符后置时重载函数要使用占位参数
- | 成员函数 | 友元函数 |
---|---|---|
重载函数声明 | Objects : : Objects operator op(int) | Objects : : Objects operator op(Object & ,int ) |
调用方式实质 | Object.operator op(0) | operator op(Object ,0) |