一 操作符(运算符)重载
1 基本概念
操作符重载的本质就是一个写具有特殊名称的函数,使用operator 后接一个操作符,比如“operator=” “operator+”,把已定义的符号来重新定义,实现程序员想要的运算功能.
eg:复数 x+yi
(1+2i) + (3+4i) = 4+6i
2 双目操作符重载 L#R
2.1 计算类双目操作符:+ -
–》左右操作数既可以是左值也可以是右值
–》表达式的结果是右值
–》两种实现方式:
1)成员函数形式(左调右参)
L#R的表达式可以被编译器处理成L.operator#®成员函数调用形式,该函数返回结果就是表达式的结果。
2)全局函数形式(左右都参)
L#R的表达式也可以被编译器处理成operator#(L,R)全局函数调用形式,该函数返回结果就是表达式的结果。
注:两种实现方式只能选择一种,一般推荐成员函数形式
注:通过friend关键字可以把一个全局函数声明为某个类的友元,友元函数可以访问类中的任何成员.
2.2 赋值类双目操作符:+= -=
–》左操作数一定是左值,右操作数既可以是左值也可以是右值
–》表达式结果是左值,就是左操作数自身
–》两种实现方式:
1)成员函数形式:L#R ==> L.operator#®
2)全局函数形式:L#R ==> operator#(L,R)
3 单目操作符重载 #O
3.1 计算类单目操作符:- ~
–》操作数可以是左值也可以是右值
–》表达式的结果是右值
–》两种实现方式:
1)成员函数形式: #O ==> O.operator#();
2)全局函数形式: #O ==> operator#(O);
3.2 自增减单目操作符:++ –
1)前缀自增减
–》操作数必须是左值
–》表达式结果是左值,就是操作数的自身
–》两种实现方式:
成员函数形式: #O ==> O.operator#();
全局函数形式: #O ==> operator#(O);
2)后缀自增减
–》操作数必须是左值
–》表示结果是右值,操作数自增减之前副本
–》两种实现方式:
成员函数形式: O# ==> O.operator#(int/哑元/);
全局函数形式: O# ==> operator#(O,int/哑元/);
4 其它操作符重载
1)输出(<<)和输入(>>)操作符重载
功能:实现自定义类型对象的输出和输入
注:只能使用全局函数形式
friend ostream& operator<<(
ostream& os,const RIGHT& r){…}
friend istream& operator>>(
istream& is,RIGHT& r){…}
#include <iostream>
ostream //标准输出流类
istream //标准输入流类
ostream cout;
istream cin;
//全局 operator<<(cout,a)
cout << a;
cout << c ...
//全局 operator>>(cin,a)
cin >> a;
2)下标操作符重载 []
功能:让对象可以像数组一样去使用
注:常对象返回时右值,非常对象返回左值
string s = “hello”;
s[0] = ‘H’;//s.operator = ‘H’
const string s = "hello";
s[0] = 'H';//s.operator[](0) = 'H',应该error
练习:实现3*3矩阵,支持如下操作符
+ - += -= -(取负) ++、-- <<
* *= []
1 2 3 9 8 7 10 10 10
4 5 6 + 6 5 4 = 10 10 10
7 8 9 3 2 1 10 10 10
1 2 3 9 8 7 -8 -6 -4
4 5 6 - 6 5 4 = -2 0 2
7 8 9 3 2 1 4 6 8
1 2 3 9 8 7 30 24 18
4 5 6 * 6 5 4 = 84 69 54
7 8 9 3 2 1 138 114 90
1 2 3 -1 -2 -3
- 4 5 6 = -4 -5 -6
7 8 9 -7 -8 -9
1 2 3
m1 = 4 5 6
7 8 9
m1[1][2] ==> 6
3)函数操作符 () //了解
功能:让对象可以当做函数来使用
注:对参数的个数、参数类型、返回类型没有任何限制
class A{};
A a1;
a1(100,3.14);//a1.operator()(100,3.14)
4)new/delete操作符 //了解
static void* operator new(size_t size){…}
static void operator delete(void* p){…}
5 操作符重载的限制
1)不能重载的操作符
–> 作用域限定操作符 “::”
–> 直接成员访问操作符 “.”
–> 直接成员指针解引用操作符 “.*”
–> 条件操作符 “?:”
–> 字节长度操作符 “sizeof”
–> 类型信息操作符 “typeid” //后面讲
2)如果一个操作符的所有操作数都是基本类型,无法重载
3)不能通过操作符重载的机制发明新的符号
4)操作符重载无法改变操作符的优先级
5)操作符重载不能改变操作数的个数
6)只能用成员函数实现的操作符
= () [] ->