小记:静默如初,安之若素
操作符重载
1. 双目操作符重载 L#R
1.1 运算类的双目操作符: + ,- ,…(需要保持语义一致和逻辑一致)
–>左右操作数既可以是左值也可以是右值;
–>表达式结果是右值
–>两种实现方式:
1)成员函数形式
L#R的表达式可以被编译器翻译成L.operator#®这样成员函数调用形式,该函数的返回结果就是表达式的结果。(L表示左操作对象,R表示右操作对象,左调(调用对象)右参(参数对象))
2)全局函数形式
L#R的表达式可以被编译器翻译成::operator#®这样全局函数调用形式,该函数的返回结果就是表达式的结果。(L表示左操作对象,R表示右操作对象)
注:使用”friend“关键字,可以把一个全局函数声明为某个类的友元,友元函数可以访问类中的任何成员。
1 #include <iostream>
2 using namespace std;
3
4 class Complex
5 {
6 public:
7 Complex(int r, int i):m_r(r), m_i(i){}
8 void print(void)
9 {
10 cout << m_r << " + " << m_i << 'i' << endl;
11 }
12
13 //成员函数形式
14 //c1+c3 ==>c1/operator+(c2)
15 //const 的作用
16 /*
17 1)修饰返回值,为了返回右值
18 2)常引用,为了支持常量型右操作数(右值)
19 3)常函数,为了支持常量型左操作数(右值)
20 */
21 const Complex operator+(const Complex& c) const
22 {
23 Complex res(m_r + c.m_r, m_i + c.m_i);
24 return res;
25 }
26 private:
27 int m_r;//实部
28 int m_i;//虚部
29 // 友元函数可以访问类中的私有成员
30 friend const Complex operator-(const Complex& l, const Complex & r);
31 };
32
33 //全局函数形式
34 const Complex operator-(const Complex& l, const Complex & r)
35 {
36 Complex res(l.m_r - r.m_r, l.m_i - r.m_i);//error,私有成员只能在类的内部访问,需加friend关键字
37 return res;
38 }
39
40 int main(void)
41 {
42 Complex c1(1, 2);
43 Complex c2(3, 4);
44 c1.print();
45 c2.print();
46 //c1.operator+(c2)
47 Complex c3 = c1 + c2;
48 c3.print();
49
50 //::operator-(c2, c1)
51 c3 = c2 - c1;
52 c3.print();
53 return 0;
54 }
1.2 赋值类的双目操作符:+=,-=,…
–>左操作数必须是左值,右操作数可以是左值也可以是右值;
–>表达式的结果是左值,就是左操作数的自身;
–>两种实现方式:
1)成员函数形式:
L # R ==> L.operator#(R)
2)全局函数形式
L # R ==>::operator#(L, R)
1 #include <iostream>
2 using namespace std;
3
4 class Complex
5 {
6 public:
7 Complex(int r, int i):m_r(r), m_i(i){}
8 void print(void)
9 {
10 cout << m_r << " + " << m_i << 'i' << endl;
11 }
12
13 //+=:成员函数形式
14 Complex &operator +=(const Complex &c)
15 {
16 m_r += c.m_r;
17 m_i += c.m_i;
18 return *this;
19 }
20
21 private:
22 int m_r;//实部
23 int m_i;//虚部
24
25 //友元函数可以把定义直接写在类的内部,但是
26 //它不属于类,本质还是全局函数。
27 friend Complex& operator-=(Complex &l, const Complex &r)
28 {
29 l.m_r -= r.m_r;
30 l.m_i -= r.m_i;
31 return l;
32 }
33 };
34
35 int main(void)
36 {
37 Complex c1(1, 2);
38 Complex c2(3, 4);
39 c1 += c2;//c1.operator+=(c2)
40 c1.print();//4 + 6i
41
42 c1 -= c2;//::operator-=(c1, c2)
43 c1.print();//1+2i
44 return 0;
45 }
规律总结:1)写操作符重载函数时,如果考虑表达式的返回结果是右值,例如+,-,它的返回值一般加const不加引用,如果是左值的话一般加引用不加const;
2)如果其参数可以是左值,也可以是右值则都是拿常引用来接收,加引用为了提高传参效率,加const是为了支持右值中常量的操作;
3)如果操作数只能是左值,加引用是为了提高传参效率
2. 单目操作符重载 #O(表达式结果是右值)
2.1 计算类的单目操作符:-(取负) ~…
–>操作数可以是左值也可以是右值
–>表达式结果是右值
–>两种实现方式:
1)成员函数形式:
#O == 》O.operator#();
2)全局函数形式:
#O ==》::operator#(O);
1 #include <iostream>
2 using namespace std;
3
4 class Integer
5 {
6 public:
7 Integer(int i = 0):m_i(i){}
8 void print(void) const
9 {
10 cout << m_i << endl;
11 }
12 //-:成员函数形式
13 const Integer operator-(void) const
14 {
15 Integer res(-m_i);
16 return res;
17 }
18 //~:全局函数形式(自定义表示乘方)
19 friend const Integer operator~(const Integer& i)
20 {
21 Integer res(i.m_i * i.m_i);
22 return res;
23 }
24 private:
25 int m_i;
26 };
27
28 int main(void)
29 {
30 Integer i(100);
31 Integer j = -i;
32 j.print();
33
34 j = ~i;
35 j.print();
36
37 return 0;
38 }
~
2.2 自增减单目操作符:前后++, –
1)前++,–
–》操作数必须是左值
–》表达式结果也是左值,就是操作数的自身
成员函数:#O==>O.operator#()
全局函数:#O==>::operator#(O)
eg:
int a = 1;
cout << ++a << endl;//2
cout << a << endl;//2
++a = 10;//OK
cout << a << endl;//10
2)后++,–
–》操作数必须是左值
–》表达式的结果应该是右值,是操作数自增减前的副本
成员函数:#O==>O.operator#(哑元参数)//增加哑元参数为了于前缀表达式进行区分
全局函数:#O==>::operator#(O,哑元参数)
eg:
int a = 1;
cout << a++ << endl;//1
cout << a << endl;//1
1 #include <iostream>
2 using namespace std;
3
4 class Integer
5 {
6 public:
7 Integer(int i = 0):m_i(i){}
8 void print(void) const
9 {
10 cout << m_i << endl;
11 }
12
13 //前++,成员函数形式
14 Integer& operator++(void)
15 {
16 ++m_i;
17 return *this;
18 }
19
20 //前--,全局函数形式
21 friend Integer& operator--(Integer& i)
22 {
23 --i.m_i;
24 return i;
25 }
26
27 //后++,成员函数形式
28 const Integer operator++(int)
29 {
30 Integer old = *this;
31 ++*this;//++m_i
32 return old;
33 }
34 //后--,全局函数形式
35 friend const Integer operator--(Integer& i, int)
36 {
37 Integer old = i;
38 --i.m_i;
39 return old;
40 }
41 private:
42 int m_i;
43 };
44
45 int main(void)
46 {
47 Integer i(100);
48
49 //前++
50 Integer j = ++i;//i.operator++()
51 i.print();//101
52 j.print();//101
53
54 j = ++++++i;//104
55 i.print();
56 j.print();
57
58 //前--
59 j = --i;//::operator--(i)
60 i.print();//103
61 j.print();//103
62
63 j = ------i;//100
64 i.print();
65 j.print();
66
67 //后++
68 j = i++;//i.operator++(0)
69 i.print();//101
70 j.print();//100
71
72 //后--
73 j = i--;//::operator--(i, 0)
74 i.print();//100
75 j.print();//101
76
77
78 return 0;
79 }
- 插入和提取操作符:<< >>
功能:实现自定义类型对象的直接输出和输入。
注:只能用全局函数形式
1)cout>>语法形式:
friend ostream& operator<<(ostream& os, const RIGHT& right){...}
2)cin>>语法形式:
friend istream& operator>>(istream& is, RIGHT& right){...}
1 #include <iostream>
2 using namespace std;
3
4 class Complex
5 {
6 public:
7 Complex(int r, int i):m_r(r), m_i(i){}
8 friend ostream& operator<<(ostream& os, const Complex& c)
9 {
10 os << c.m_r << "+" << c.m_i << "i";
11 return os;
12 }
13
14 friend istream& operator>>(istream& is, Complex& c)
15 {
16 is >> c.m_r >> c.m_i;
17 return is;
18 }
19
20 private:
21 int m_r;//实部
22 int m_i;//虚部
23 };
24
25
26 int main(void)
27 {
28 Complex c1(1, 2);
29 Complex c2(3, 4);
30
31 //::operator<<(cout, c1);
32 cout << c1 << endl;
33 cout << c1 << ',' << c2 << endl;
34
35 Complex c3(0, 0);
36 cout <<"Input complex(shibu, xubu) : ";
37 cin >> c3;//operator>>(cin, c3);
38 cout << c3 << endl;
39 return 0;
40 }
总结:实现上述的操作符重载
1 #include <iostream>
2 #include <iomanip>
3 using namespace std;
4
5 class M33
6 {
7 public:
8 M33(void)
9 {
10 for(int i = 0; i < 3; i++)
11 {
12 for(int j = 0; j < 3; j++)
13 {
14 m_a[i][j] = 0;
15 }
16 }
17 }
18
19 M33(int a[][3])
20 {
21 for(int i = 0; i < 3; i++)
22 {
23 for(int j = 0; j < 3; j++)
24 {
25 m_a[i][j] = a[i][j];
26 }
27 }
28 }
29
30 //重载操作符<<
31 friend ostream& operator<<(ostream& os, const M33& m)
32 {
33 for(int i = 0; i < 3; i++)
34 {
35 for(int j = 0; j < 3; j++)
36 {
37 //setw(4):设置数据域宽
38 os << setw(4) << m.m_a[i][j];
39 }
40 os << endl;
41 }
42 return os;
43 }
44
45 //+
46 const M33 operator+(const M33 &m) const
47 {
48 int res[3][3] = {0};
49 for(int i = 0; i < 3; i++)
50 {
51 for(int j = 0; j < 3; j++)
52 {
53 res[i][j] = m_a[i][j] + m.m_a[i][j];
54 }
55 }
56 return M33(res);
57 }
58
59 //-
60 const M33 operator-(const M33 &m) const
61 {
62 int res[3][3] = {0};
63 for(int i = 0; i < 3; i++)
64 {
65 for(int j = 0; j < 3; j++)
66 {
67 res[i][j] = m_a[i][j] - m.m_a[i][j];
68 }
69 }
70 return M33(res);
71 }
72 //+=
73 M33& operator+=(const M33& m)
74 {
75 *this = *this + m;
76 return *this;
77 }
78
79 //-=
80 M33& operator-=(const M33& m)
81 {
82 *this = *this - m;
83 return *this;
84 }
85
86 //-(取负)
87 const M33 operator-(void) const
88 {
89 //M33():以无参的方式创建临时对象
90 return M33() - *this;
91 }
92
93 private:
94 int m_a[3][3];
95 };
96
97
98 int main(void)
99 {
100 int a1[3][3] = {1,2,3,4,5,6,7,8,9};
101 M33 m1(a1);
102
103 int a2[3][3] = {9,8,7,6,5,4,3,2,1};
104 M33 m2(a2);
105
106 cout << m1 << endl;
107 cout << m2 << endl;
108
109 cout << "m1 + m2 : " << endl;
110 cout << m1 + m2 << endl;
111 cout << "m1 - m2 : " << endl;
112 cout << m1 - m2 << endl;
113
114 cout << "m1 += m2 :" << endl;
115 cout << (m1+=m2) << endl;
116 cout << m1 << endl;
117 cout << "m1 -= m2 :" << endl;
118 cout << (m1-=m2) << endl;
119 cout << m1 << endl;
120
121 cout << "-m1 : "<< endl;
122 cout << -m1 << endl;
123
124 return 0;
125 }
4. 下标操作符重载 [ ]
功能:让一个对象像数组一样去使用。
注:非常对象返回左值,常对象返回右值
5. 函数操作符()
功能:让一个对象可以像函数一样去使用。
注:对参数个数,参数类型,返回值类型没有限制。
6. new/delete操作符
语法形式:
static void *operator new(size_t size){...}
static void operator delete(void *p){...}
- 总结:操作符重载的限制
1)不是所有操作都可以重载,下列操作符不能重载:
1.1)作用域限定操作符 "::";
1.2)直接成员访问操作符 " . "
1.3)直接成员指针解引用操作符 " .* "
1.4)条件操作符 "?"
1.5)字节长度操作符 "sizeof"
1.6)类型信息操作符 "typeid"
2)如果一个操作符的所有操作数都是基本类型,则无法实现重载;
eg:
int operator+(int a, int b){return a-b};//error, 必须有一个自定义类型
3)操作符重载不会改变编译器预定义的优先级;
4)操作符的重载不能翻遍操作数的个数;
5)无法通过操作符重载发明新的操作符。