重载操作符是具有特殊名称的函数:保留字operator后接需定义的操作符符号。除了函数调用操作符之外,重载操作符的形参数目(包括成员函数的隐式this指针)与操作符的操作数数目相同。函数调用操作符可以接受任意数目的操作数。
大多数操作符都可以重载,所以我列出不能重载的操作符,一共有四种:
:: .* . ?:
当操作符为类的成员函数时,this指向左操作数。
下面通过实例说明操作符重载
源代码下载:点击下载。
1.算术操作符
定义一个Point类,Point.h头文件:
// Point.h: interface for the Point class.
//
//
#if !defined(AFX_POINT_H__E8270DD2_C889_4B24_BC82_E154B77FDFCF__INCLUDED_)
#define AFX_POINT_H__E8270DD2_C889_4B24_BC82_E154B77FDFCF__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class Point
{
public:
Point();
Point(int x,int y);
virtual ~Point();
int getX();
int getY();
Point operator+(const Point&);
private:
int x,y;
};
#endif // !defined(AFX_POINT_H__E8270DD2_C889_4B24_BC82_E154B77FDFCF__INCLUDED_)
Point.cpp源文件:
// Point.cpp: implementation of the Point class.
//
//
#include "Point.h"
//
// Construction/Destruction
//
Point::Point()
{
}
Point::Point(int x,int y)
{
this->x=x;
this->y=y;
}
Point::~Point()
{
}
Point Point::operator +(const Point &pt)
{
Point p(*this);
p.x+=pt.x;
p.y+=pt.y;
return p;
}
int Point::getX()
{
return this->x;
}
int Point::getY()
{
return this->y;
}
在这里,我要重载Point类的加号操作符,实现两个点的x和y分别相加,返回一个Point对象,返回的Point对象的x为两个Point的x的和,y为两个Point的y相加。
主类:
#include<iostream>
#include<algorithm>
#include "Point.h"
using namespace std;
int main()
{
Point pt1(3,4);
Point pt2(4,5);
Point pt3=pt1+pt2;
cout<<pt3.getX()<<endl<<pt3.getY()<<endl;
return 0;
}
在这里要注意了,不能返回一个局部自定义类型的引用或者指针,因为函数结束之后,内存被释放,再去使用的话,会出现不可预知的错误。
2.关系操作符
在头文件中定义两个函数:
bool operator==(const Point&);
bool operator!=(const Point&);
在源文件中实现这个函数:
bool Point::operator==(const Point &pt)
{
return this->x==pt.x&&this->y==pt.y;
}
bool Point::operator!=(const Point &pt)
{
return !(*this==pt);
}
因为前面定义了==的操作符,所以后面的!=操作符可以使用==操作符。在定义关系操作符的时候一定要注意如果==返回真,则!=返回假。
3.自增操作符和自减操作符
这样的操作符的难点是这两个符号既可以在对象之前,也可以在对象之后,我先实现在对象之前的操作符重载。
在头文件中定义函数:
Point& operator++();
Point& operator--();
在源文件中如此实现:
Point& Point::operator ++()
{
this->x++;
this->y++;
return *this;
}
Point& Point::operator --()
{
x--;
y--;
return *this;
}
在主函数中测试如下:
#include<iostream>
#include<algorithm>
#include "Point.h"
using namespace std;
int main()
{
Point pt1(3,4);
Point pt2(4,5);
++pt1;
--pt2;
cout<<pt1.getX()<<pt1.getY()<<endl<<pt2.getX()<<pt2.getY()<<endl;
//cout<<(pt1==pt2)<<endl<<(pt1==pt1)<<endl<<(pt1!=pt2)<<endl;
return 0;
}
同时定义前缀式操作符与后缀式操作符存在一个问题:他们的形参数目和类型相同,普通重载不能区别所定义的是前缀式操作符还是后缀式操作符。
为了解决这一问题,后缀式操作符接受一个额外的int形参。使用后缀式操作符时,编译器提供0作为这个形参的实参。尽管我们的前缀式操作符可以使用这个额外的形参,但通常不应该这样做。那个形参不是后缀式操作符的正常工作所需要的,它的唯一作用是使后缀式函数与前缀式函数区别开。
在头文件中定义如下:
Point operator++(int);
Point operator--(int);
在源文件中实现:
Point Point::operator ++(int)
{
Point p(*this);
++*this;
return p;
}
Point Point::operator --(int)
{
Point p(*this);
--*this;
return p;
}
在主函数中测试成功:
#include<iostream>
#include<algorithm>
#include "Point.h"
using namespace std;
int main()
{
Point pt1(3,4);
Point pt2(4,5);
// ++pt1;
// --pt2;
//cout<<pt1.getX()<<pt1.getY()<<endl<<pt2.getX()<<pt2.getY()<<endl;
//cout<<(pt1==pt2)<<endl<<(pt1==pt1)<<endl<<(pt1!=pt2)<<endl;
Point pt3=pt1--;
cout<<pt3.getX()<<endl<<pt3.getY()<<endl;
return 0;
}
打印的是pt1自减之前的值。
注意:使用对象显式调用后缀式自减或自加时,应该传入一个参数:
Point pt;
pt.operator++(0); 这样就是调用后缀式的操作。
4.下标操作符
小标操作应该注意,在用作赋值的左右操作数时,都应该表现的正常。所以,这就要求返回的类型应该为引用。
小面定义一个类China,包含省级行政单位,定义在hina.h头文件中:
#if !defined(AFX_HINA_H__2E76F1BB_EE30_4584_9C8F_C46A4C613620__INCLUDED_)
#define AFX_HINA_H__2E76F1BB_EE30_4584_9C8F_C46A4C613620__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif
#include <string>
class China
{
public:
China();
std::string& operator[](const int index);
virtual ~China();
private:
std::string *province;
};
#endif
源文件为hina.cpp,如下实现:
#include "hina.h"
China::China()
{
province=new std::string[34];
province[0]=std::string("山西省");
province[1]=std::string("湖北省");
province[2]=std::string("北京市");
}
China::~China()
{
delete []province;
}
std::string& China::operator [](const int index)
{
if(index<0||index>34)
return std::string("有错误");
return province[index];
}
这样就保证下标返回返回的值既可以是左值,又是右值。在main函数中测试通过:
#include <iostream>
#include "hina.h"
using namespace std;
int main()
{
China c;
c[0]="张译成";
cout<<c[0]<<endl;
return 0;
}
我将山西省换成我的名字,就改变了c对象中的值,c[0]="张译成";中,c[0]是左值,cout<<c[0]<<endl;中c[0]是右值。表现正常。