运算符重载,就是对已有的运算符重新进行定义,赋予其另一种功能,使他适应不同的数据类型。
运算符重载的本质:函数重载 关键字:operator
一、一元运算符重载
一元运算符就是对一个数进行操作
一元运算符重载利用成员函数进行重载时,就不用给()内传参数了,()内有隐藏的*this
负号运算符的重载
定义一个Coordinate坐标类,分别通过成员函数和友元函数对负号运算符进行重载
通过成员函数对负号运算符进行重载:
#include<iostream>
using namespace std;
/******************************************
一元运算符重载
要求:
定义一个Coordinate坐标类
成员函数:构造、getX、getY,数据成员:m_iX,m_iY
1、负号运算符重载(成员函数,友元函数)
2、++运算符重载(前置++,后置++)
*******************************************/
class Coordinate
{
Coordinate(int x,int y);
//通过成员函数对符号运算符进行重载
Coordinate &operator-();//让他返回出来的是它本身,这样才能让他再进行负号运算符的运算,所以返回值写成Coordinate &
int getX();
int getY();
private:
int m_iX;
int m_iY;
};
Coordinate::Coordinate(int x,int y)
{
m_iX = x;
m_iY = y;
}
int Coordinate::getX()
{
return m_iX;
}
int Coordinate::getY()
{
return m_iY;
}
//成员函数实现负号运算符重载
Coordinate &Coordinate::operator-()
{
this->m_iX = -(this->m_iX);//m_iX = -m_iX;
this->m_iY = -(this->m_iY);
return *this;//返回的是一个对象
}
int main()
{
Coordinate coor1(1,3);
cout<<coor1.getX()<<","<<coor1.getY()<<endl;
-coor1;//coor1.operator-();成员函数
cout<<coor1.getX()<<","<<coor1.getY()<<endl;
return 0;
}
运行结果:
通过友元函数对负号运算符进行重载:
#include<iostream>
using namespace std;
/******************************************
一元运算符重载
要求:
定义一个Coordinate坐标类
成员函数:构造、getX、getY,数据成员:m_iX,m_iY
1、负号运算符重载(成员函数,友元函数)
2、++运算符重载(前置++,后置++)
*******************************************/
class Coordinate
{
friend Coordinate &operator-(Coordinate &c);//friend Coordinate &operator-(Coordinate c);
//()内要传入参数,其实就是在成员函数重载中要传入的*this,所以应该是Coordinate的一个对象,为了传递效率,也可以传入一个对象的引用
public:
Coordinate(int x,int y);
int getX();
int getY();
private:
int m_iX;
int m_iY;
};
Coordinate::Coordinate(int x,int y)
{
m_iX = x;
m_iY = y;
}
int Coordinate::getX()
{
return m_iX;
}
int Coordinate::getY()
{
return m_iY;
}
Coordinate &operator-(Coordinate &c)//友元函数重载符号运算符
{
c.m_iX = -c.m_iX;
c.m_iY = -c.m_iY;
return c;
}
int main()
{
Coordinate coor1(1,3);
cout<<coor1.getX()<<","<<coor1.getY()<<endl;
operator-(coor1);//-coor1;
cout<<coor1.getX()<<","<<coor1.getY()<<endl;
return 0;
}
运行结果:
前置++、后置++重载
#include<iostream>
using namespace std;
Coordinate
{
public:
Coordinate(int x,int y);
Coordinate &operator++();//前置++的运算符重载,返回的是一个Coordinate的引用
Coordinate operator++(int);//后置++的运算符重载,参数int只是为了表示当前的++是后置++
//返回的是一个对象而不是引用,是因为后置++是在下一行代码再去访问这个对象的时候才会返回++之后的值,如果返回引用的话,函数结束后,引用就会被释放
int getX();
int getY();
private:
int m_iX;
int m_iY;
};
Coordinate::Coordinate(int x,int y)
{
m_iX = x;
m_iY = y;
}
int Coordinate::getX()
{
return m_iX;
}
int Coordinate::getY()
{
return m_iY;
}
Coordinate &Coordinate::operator++()//前置++
{
++m_iX;
++m_iY;
return *this;
}
Coordinate Coordinate::operator++(int)//后置++
{
Coordinate old(*this);//利用默认拷贝构造函数构造一个临时对象old,将++之前的值存储在临时对象old中
this->m_iX++;
this->m_iY++;
return old;//当前这个表达式是他++之前的值,下一行代码再去访问这个对象的时候,才是++之后的值
}
int main()
{
Coordinate coor1(1,3);
cout<<coor1.getX()<<","<<coor1.getY()<<endl;//1,3
coor1.operator++(0);//参数0只是标识是后置++
cout<<coor1.getX()<<","<<coor1.getY()<<endl;//2,4
cout<<(coor1++).getX()<<",";//2
cout<<(coor1++).getY()<<endl;//5
return 0;
}
运行结果:
二、二元运算符重载
1、“+号”运算符重载(成员函数,友元函数)
2、“<<”输出运算符重载
3、“[]索引”运算符重载
#include<iostream>
using namespace std;
/******************************************
二元运算符重载
要求:
定义一个Coordinate坐标类
成员函数:构造、getX、getY,数据成员:m_iX,m_iY
1、“+号”运算符重载(成员函数,友元函数)
2、“<<”输出运算符重载
3、“[]索引”运算符重载
*******************************************/
class Coordinate
{
//“<<”输出运算符重载
friend ostream& operator<<(ostream &output,const Coordinate &c);//返回值是ostream
//“+号”运算符通过友元函数重载
friend Coordinate operator+(const Coordinate &c1,const Coordinate &c2);
public:
Coordinate(int x,int y);
//“+号”运算符通过成员函数重载,不能传引用,要传对象
//Coordinate operator+(const Coordinate &c);
//“[]索引”运算符重载
int operator[](int index);
int getX();
int getY();
private:
int m_iX;
int m_iY;
};
Coordinate::Coordinate(int x,int y)
{
m_iX = x;
m_iY = y;
}
int Coordinate::getX()
{
return m_iX;
}
int Coordinate::getY()
{
return m_iY;
}
/*“+号”运算符通过成员函数重载
Coordinate Coordinate::operator+(const Coordinate &c)
{
Coordinate temp(0,0);
temp.m_iX = this->m_iX + c.m_iX;
temp.m_iY = this->m_iY + c.m_iY;
return temp;
}
*/
//“+号”运算符通过友元函数重载
Coordinate operator+(const Coordinate &c1,const Coordinate &c2)
{
Coordinate temp(0,0);
temp.m_iX = c1.m_iX + c2.m_iX;
temp.m_iY = c1.m_iY + c2.m_iY;
return temp;
}
//“<<”输出运算符重载
ostream& operator<<(ostream &output,const Coordinate &c)//返回值为ostream&,const Coordinate &c为要进行输出的对象
{
output<<c.m_iX<<","<<c.m_iY<<endl;
return output;
}
//“[]索引”运算符重载
int Coordinate::operator[](int index)
{
if(0 == index)
{
return m_iX;
}
if(1 == index)
{
return m_iY;
}
}
int main()
{
Coordinate coor1(1,3);
Coordinate coor2(2,4);
Coordinate coor3(0,0);
coor3 = operator+(coor1,coor2);
//coor3 = coor1 + coor2;
cout<<coor3.getX()<<","<<coor3.getY()<<endl;//3,7
operator<<(cout,coor1);//1,3
cout<<coor2;//2,4
cout<<coor2[0];//2
cout<<coor2[1];//4
return 0;
}
运行结果:
注:
- “<<”输出运算符重载不能用成员函数进行重载,只能用友元函数进行重载;因为在成员函数中重载第一个参数为隐藏的*this,而“<<”输出运算符重载第一个参数为ostream &output
- “[]索引”运算符重载不能用友元函数进行重载,只能用成员函数进行重载;因为“[]索引”运算符重载第一个参数必须为*this,通过*this才能访问到该对象的数据
- 赋值运算符重载函数不能被继承
因为相较于基类,派生类往往要添加一些自己的数据成员和成员函数,如果允许派生类继承基类的赋值运算符重载函数,那么,在派生类不提供自己的赋值运算符重载函数时,就只能调用基类的,但基类版本只能处理基类的数据成员,在这种情况下,派生类自己的数据成员怎么办? 所以,C++规定,赋值运算符重载函数不能被继承。
- 赋值运算符重载函数只能是类的非静态的成员函数,不能是静态成员函数,也不能是友元函数
其实,之所以不是静态成员函数,是因为静态成员函数只能操作类的静态成员,不能操作非静态成员。如果我们将赋值运算符重载函数定义为静态成员函数,那么,该函数将无法操作类的非静态成员,这显然是不可行的。
三、可重载运算符/不可重载运算符
下面是可重载的运算符列表:
双目算术运算符 | + (加),-(减),*(乘),/(除),% (取模) |
关系运算符 | ==(等于),!= (不等于),< (小于),> (大于>,<=(小于等于),>=(大于等于) |
逻辑运算符 | ||(逻辑或),&&(逻辑与),!(逻辑非) |
单目运算符 | + (正),-(负),*(指针),&(取地址) |
自增自减运算符 | ++(自增),--(自减) |
位运算符 | | (按位或),& (按位与),~(按位取反),^(按位异或),,<< (左移),>>(右移) |
赋值运算符 | =, +=, -=, *=, /= , % = , &=, |=, ^=, <<=, >>= |
空间申请与释放 | new, delete, new[ ] , delete[] |
其他运算符 | ()(函数调用),->(成员访问),,(逗号),[](下标) |
下面是不可重载的运算符列表:
- .:成员访问运算符
- .*, ->*:成员指针访问运算符
- :::域运算符
- sizeof:长度运算符
- ?::条件运算符
- #: 预处理符号
还可参考:一文说尽C++赋值运算符重载函数(operator=)