3.运算符重载

一、操作符函数
 在C++中,编译器有能力把一个由数据、对象和操作符共同组成的表达式,解释为对一个全局或成员函数的调用。
 该全局或成员函数被称为操作符函数,通过重定义操作符函数,可以实现针对自定义类型的运算法则,并使之与内置类型一样参与各种表达式。
 
二、双目操作符表达式
  成员函数
    形如L#R双目操作符表达式,将被编译器解释为 L.operator#(R)
    a-b+c == a.operator-(b).operator+(c)
  全局函数
    形如L#R的双目操作符表达式,将被编译器解释为 ::operator#(L,R)
    a-(b+c) == ::operator-(a,::operator+(b,c))
 
 
三、单目操作符表达式
  成员函数
    形如#O或O#的单目操作表达式,将被编译器解释为 O.operator#(),唯一的操作数是调用对象。
  全局函数
    形如#O或O#的单目操作表达式,将被编译器解释为 ::operator#(O),唯一的操作数是调用对象。
 
 
以下所有重载的代码实例
  1 #include <iostream>
  2 using namespace std;
  3 
  4 
  5 
  6 struct Point 
  7 {
  8     int x;
  9     int y;
 10 
 11 public:
 12     Point(int _x=0,int _y=0)
 13     {
 14         x = _x;
 15         y = _y;
 16     }
 17 
 18     Point(Point &that)
 19     {
 20         x = that.x;
 21         y = that.y;
 22     }
 23 
 24     Point &operator = (Point &that)
 25     {
 26         x = that.x;
 27         y = that.y;
 28     }
 29 
 30     void show()
 31     {
 32         cout << "x=" << x << "," << "y=" << y << endl;
 33     }
 34 
 35     Point operator - (Point &that)
 36     {
 37         Point t;
 38         t.x = x-that.x;
 39         t.y = y-that.y;
 40         return t;
 41     }
 42 
 43     Point operator +(Point &that)
 44     {
 45         Point t;
 46         t.x = x+that.x;
 47         t.y = y+that.y;
 48         return t;
 49     }
 50 
 51 /*
 52 
 53     Point& operator --(void)
 54     {
 55         --x;
 56         --y;
 57         return *this;
 58     }
 59 
 60 
 61     Point operator --(int)
 62     {
 63         Point t(*this);
 64         --x;
 65         --y;
 66         return t;
 67     }
 68 
 69 
 70 */
 71 
 72     int operator [](int index)
 73     {
 74         return !index ?x:y;
 75     }
 76 
 77 /*
 78     Point operator *(Point &that)
 79     {
 80         Point t;
 81         t.x = x*that.x;
 82         t.y = y*that.y;
 83         return t;
 84     }
 85 
 86 */
 87     friend Point operator %(Point &p1,Point &p2);
 88     friend Point operator *(Point &p1,Point &p2);
 89     friend Point &operator --(Point &p1);
 90     friend Point operator --(Point &p1,int);
 91     friend istream & operator >> (istream &is,Point &p1);
 92 
 93 
 94 };
 95 
 96 
 97 
 98 Point operator %(Point &p1,Point &p2)
 99 {
100     Point p3(p1.x%p2.x,p1.y%p2.y);
101     return p3;
102 }
103 
104 Point operator *(Point &p1,Point &p2)
105 {
106     cout << "我是友元" << endl;
107     Point p3(p1.x*p2.x,p1.y*p2.y);
108     return p3;
109 }
110 
111 
112 Point &operator --(Point &p1)
113 {
114     --p1.x;
115     --p1.y;
116     return p1;
117 }
118 
119 Point operator --(Point &p1,int)
120 {
121     Point t(p1);
122     --p1.x;
123     --p1.y;
124     return t;
125 }
126 
127 
128 istream & operator >> (istream &is,Point &p1)
129 {
130     return    is >> p1.x >> p1.y;
131 }
132 
133 
134 
135 
136 int main()
137 {
138     Point p1(1,2);
139     p1.show();
140     Point p2(2,3);
141     p2.show();
142 
143 
144     Point p3;
145     cin >> p3;
146     p3.show();
147     cout <<    p3[0] << p3[1] << endl;
148 
149 }
Point重载所有运算符

 

 
四、典型的双目运算符重载
 成员函数
1  Point operator /+-*%|^& (Point& that)
2  {
3   Point t; // 会调用无参构造
4   t.x = x / that.x;
5   t.y = y / that.y;
6   return t; // 不能返回局部对象的引用,否则会出现悬空引用
7  }

 

 注意:原对象的值不变,要产生一个临时的对象
 
 1  bool operator > < >= <= == != || && (Point& that)
 2  {
 3  
 4  }
 5  
 6  Point& operator += -= *= /= (Point& that)
 7  {
 8  
 9   return *this;
10  }

 

 
 注意:运算符的重载要符合情理。
 
 全局函数
 可能会访问到参数的私有成员:
  1、把成员变成公开,但会破坏类的封闭性。
  2、把全局函数声明为友元(友元不是成员),
  3、不能在友元函数中直接访问成员变量。
1  Point operator + (Point& a,Point& b)
2  {
3   Point t(a.x+b.x,a.y+b.y);
4   return t;
5  }

 

 
五、典型的单目运算符重载
 成员函数:
 前++/--
1  Point& operator ++/-- (void)
2  {
3  
4  }

 

 
 后++/--
1  Point operator ++/-- (int)
2  {
3  
4  }

 

 
 全局函数:
 前++/--
1  Point& operator ++/-- (Point&)
2  {
3  
4  }
5  

 

 后++/--
1  Point operator ++/-- (Point&,int)
2  {
3  
4  }
5  

 

六、输入、输出运算符重载
 输入、输出运算符不能重载为成员函数,只能是友元。
1  ostream& operator << (ostream& os,Point& p)
2  {
3  
4  }
5  
6  istream& operator >> (istream& is,Point& p)
7  {
8  
9  }

 

 
七、特殊的运算符的重载
 
 [] 下标运算符,可以把对象当作数组来使用。
 () 函数运算符,可以把对象当作函数来使用。
 -> 成员访问运算符,可以把对象当作指针来使用。
 * 解引用运算符,可以把对象当作指针来使用。
 new/delete 也可以进行重载,但不建议使用。
  new会自动调用重载的new函数再构造函数。
  delete会先调用析构再调用重载的delete函数。
 
 只有极个别的运算符的重载对于对象来说是有意义(>>,<<)
  常考的运算符重载:前++/--,后++/--
 
八、运算符重载的一些限制
 1、不能重载的运算符
  :: 作用域限定符
  . 成员访问运算
  .* 成员指针解引用
  ?: 三目运算符
  sizeof 字节长度运算符
  typeid 类型信息操作符
 2、运算符的重载改变不了运算符的优先级
 3、无法改变运算符的操作个数
 4、无法发明新的运算符
 5、重载运算符要注意运算符的一致性
  不要改变运算符默认的运算规则
 6、运算符的重载是为了方便使用、增强可读,不应该成功卖弄的工具。
 
 
posted @ 2018-08-23 16:11  LyndonMario  阅读(304)  评论(0编辑  收藏  举报