C++学习总结18--操作符重载

小记:静默如初,安之若素

操作符重载

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. 插入和提取操作符:<< >>
    功能:实现自定义类型对象的直接输出和输入。
    注:只能用全局函数形式
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)作用域限定操作符 "::"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)无法通过操作符重载发明新的操作符。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值