C++集锦三 操作符重载

来源:互联网 发布:exe软件看源码 编辑:程序博客网 时间:2024/06/07 01:11

重载操作符是具有特殊名称的函数:保留字operator后接需定义的操作符符号。除了函数调用操作符之外,重载操作符的形参数目(包括成员函数的隐式this指针)与操作符的操作数数目相同。函数调用操作符可以接受任意数目的操作数。

 

大多数操作符都可以重载,所以我列出不能重载的操作符,一共有四种:

::                        .*                            .                            ?:

 

当操作符为类的成员函数时,this指向左操作数。

 

下面通过实例说明操作符重载

源代码下载:点击下载

1.算术操作符

定义一个Point类,Point.h头文件:

[cpp] view plain copy
  1. // Point.h: interface for the Point class.  
  2. //  
  3. //////////////////////////////////////////////////////////////////////  
  4.   
  5. #if !defined(AFX_POINT_H__E8270DD2_C889_4B24_BC82_E154B77FDFCF__INCLUDED_)  
  6. #define AFX_POINT_H__E8270DD2_C889_4B24_BC82_E154B77FDFCF__INCLUDED_  
  7.   
  8. #if _MSC_VER > 1000  
  9. #pragma once  
  10. #endif // _MSC_VER > 1000  
  11.   
  12. class Point    
  13. {  
  14. public:  
  15.     Point();  
  16.     Point(int x,int y);  
  17.     virtual ~Point();  
  18.     int getX();  
  19.     int getY();  
  20.     Point operator+(const Point&);  
  21. private:  
  22.     int x,y;  
  23.   
  24. };  
  25.   
  26. #endif // !defined(AFX_POINT_H__E8270DD2_C889_4B24_BC82_E154B77FDFCF__INCLUDED_)  


Point.cpp源文件:

[cpp] view plain copy
  1. // Point.cpp: implementation of the Point class.  
  2. //  
  3. //////////////////////////////////////////////////////////////////////  
  4.   
  5. #include "Point.h"  
  6.   
  7. //////////////////////////////////////////////////////////////////////  
  8. // Construction/Destruction  
  9. //////////////////////////////////////////////////////////////////////  
  10.   
  11. Point::Point()  
  12. {  
  13.   
  14. }  
  15. Point::Point(int x,int y)  
  16. {  
  17.   
  18.     this->x=x;  
  19.     this->y=y;  
  20. }  
  21.   
  22. Point::~Point()  
  23. {  
  24.   
  25. }  
  26. Point Point::operator +(const Point &pt)  
  27. {  
  28.     Point p(*this);  
  29.     p.x+=pt.x;  
  30.     p.y+=pt.y;  
  31.   
  32.     return p;  
  33. }  
  34.   
  35. int Point::getX()  
  36. {  
  37.   
  38.     return this->x;  
  39. }  
  40. int Point::getY()  
  41. {  
  42.     return this->y;  
  43. }  


在这里,我要重载Point类的加号操作符,实现两个点的x和y分别相加,返回一个Point对象,返回的Point对象的x为两个Point的x的和,y为两个Point的y相加。

主类:

[cpp] view plain copy
  1. #include<iostream>  
  2. #include<algorithm>  
  3. #include "Point.h"  
  4. using namespace std;  
  5.   
  6.   
  7. int main()  
  8. {  
  9.   
  10.     Point pt1(3,4);  
  11.     Point pt2(4,5);  
  12.     Point pt3=pt1+pt2;  
  13.   
  14.     cout<<pt3.getX()<<endl<<pt3.getY()<<endl;  

  15.     return 0;  
  16. }  


在这里要注意了,不能返回一个局部自定义类型的引用或者指针,因为函数结束之后,内存被释放,再去使用的话,会出现不可预知的错误。

2.关系操作符

在头文件中定义两个函数:

[cpp] view plain copy
  1. bool operator==(const Point&);  
  2. bool operator!=(const Point&);  


在源文件中实现这个函数:

[cpp] view plain copy
  1. bool Point::operator==(const Point &pt)  
  2. {  
  3.     return this->x==pt.x&&this->y==pt.y;  
  4. }  
  5.   
  6. bool Point::operator!=(const Point &pt)  
  7. {  
  8.     return !(*this==pt);  
  9. }  

 

因为前面定义了==的操作符,所以后面的!=操作符可以使用==操作符。在定义关系操作符的时候一定要注意如果==返回真,则!=返回假。

3.自增操作符和自减操作符

这样的操作符的难点是这两个符号既可以在对象之前,也可以在对象之后,我先实现在对象之前的操作符重载。

在头文件中定义函数:

[cpp] view plain copy
  1. Point& operator++();  
  2. Point& operator--();  


在源文件中如此实现:

[cpp] view plain copy
  1. Point& Point::operator ++()  
  2. {  
  3.     this->x++;  
  4.     this->y++;  
  5.     return *this;  
  6. }  
  7. Point& Point::operator --()  
  8. {  
  9.     x--;  
  10.     y--;  
  11.     return *this;  
  12.   
  13. }  


在主函数中测试如下:

[cpp] view plain copy
  1. #include<iostream>  
  2. #include<algorithm>  
  3. #include "Point.h"  
  4. using namespace std;  
  5.   
  6.   
  7. int main()  
  8. {  
  9.   
  10.     Point pt1(3,4);  
  11.     Point pt2(4,5);  
  12.       
  13.     ++pt1;  
  14.     --pt2;  
  15.     cout<<pt1.getX()<<pt1.getY()<<endl<<pt2.getX()<<pt2.getY()<<endl;  
  16.     //cout<<(pt1==pt2)<<endl<<(pt1==pt1)<<endl<<(pt1!=pt2)<<endl;  
  17.       
  18.     return 0;  
  19. }  

 

 

同时定义前缀式操作符与后缀式操作符存在一个问题:他们的形参数目和类型相同,普通重载不能区别所定义的是前缀式操作符还是后缀式操作符。

 

为了解决这一问题,后缀式操作符接受一个额外的int形参。使用后缀式操作符时,编译器提供0作为这个形参的实参。尽管我们的前缀式操作符可以使用这个额外的形参,但通常不应该这样做。那个形参不是后缀式操作符的正常工作所需要的,它的唯一作用是使后缀式函数与前缀式函数区别开。

在头文件中定义如下:

[cpp] view plain copy
  1. Point operator++(int);  
  2. Point operator--(int);  


在源文件中实现:

[cpp] view plain copy
  1. Point Point::operator ++(int)  
  2. {  
  3.     Point p(*this);  
  4.     ++*this;  
  5.     return p;  
  6.   
  7. }  
  8.   
  9. Point Point::operator --(int)  
  10. {  
  11.   
  12.     Point p(*this);  
  13.     --*this;  
  14.     return p;  
  15. }  


在主函数中测试成功:

[cpp] view plain copy
  1. #include<iostream>  
  2. #include<algorithm>  
  3. #include "Point.h"  
  4. using namespace std;  
  5.   
  6.   
  7. int main()  
  8. {  
  9.   
  10.     Point pt1(3,4);  
  11.     Point pt2(4,5);  
  12.       
  13. //  ++pt1;  
  14. //  --pt2;  
  15.     //cout<<pt1.getX()<<pt1.getY()<<endl<<pt2.getX()<<pt2.getY()<<endl;  
  16.     //cout<<(pt1==pt2)<<endl<<(pt1==pt1)<<endl<<(pt1!=pt2)<<endl;  
  17.     Point pt3=pt1--;  
  18.     cout<<pt3.getX()<<endl<<pt3.getY()<<endl;  
  19.     return 0;  
  20. }  


打印的是pt1自减之前的值。

 

注意:使用对象显式调用后缀式自减或自加时,应该传入一个参数:

Point pt;

pt.operator++(0);  这样就是调用后缀式的操作。


 

4.下标操作符

小标操作应该注意,在用作赋值的左右操作数时,都应该表现的正常。所以,这就要求返回的类型应该为引用。

小面定义一个类China,包含省级行政单位,定义在hina.h头文件中:

[cpp] view plain copy
  1. #if !defined(AFX_HINA_H__2E76F1BB_EE30_4584_9C8F_C46A4C613620__INCLUDED_)  
  2. #define AFX_HINA_H__2E76F1BB_EE30_4584_9C8F_C46A4C613620__INCLUDED_  
  3.   
  4. #if _MSC_VER > 1000  
  5. #pragma once  
  6. #endif   
  7. #include <string>  
  8. class China    
  9. {  
  10. public:  
  11.     China();  
  12.     std::string& operator[](const int index);  
  13.     virtual ~China();  
  14. private:  
  15.     std::string *province;  
  16.   
  17.   
  18. };  
  19.   
  20. #endif   


源文件为hina.cpp,如下实现:

[cpp] view plain copy
  1. #include "hina.h"  
  2. China::China()  
  3. {  
  4.     province=new std::string[34];  
  5.     province[0]=std::string("山西省");  
  6.     province[1]=std::string("湖北省");  
  7.     province[2]=std::string("北京市");  
  8.   
  9. }  
  10.   
  11. China::~China()  
  12. {  
  13.     delete []province;  
  14. }  
  15.   
  16. std::string& China::operator [](const int index)  
  17. {  
  18.     if(index<0||index>34)  
  19.         return std::string("有错误");  
  20.   
  21.     return province[index];  
  22. }  

这样就保证下标返回返回的值既可以是左值,又是右值。在main函数中测试通过:

[cpp] view plain copy
  1. #include <iostream>  
  2. #include "hina.h"  
  3. using namespace std;  
  4. int main()  
  5. {  
  6.     China c;  
  7.     c[0]="张译成";   
  8.     cout<<c[0]<<endl;  
  9.     return 0;  
  10. }  


我将山西省换成我的名字,就改变了c对象中的值,c[0]="张译成";中,c[0]是左值,cout<<c[0]<<endl;中c[0]是右值。表现正常。

原创粉丝点击