C++中允许我们对类类型(class类型)重定义运算符,即运算符重载
类类型的运算符重载的固定格式:
(返回值类型) operator<待重载的运算符> (参数列表)
在C++中可重载的运算符有:
+ - * / % ^ & | ~ ! , = < > <= >= ++ -- << >> == != && || += -=
/= %= ^= &= |= *= <<= >>= [] () -> ->* new new[] delete delete[]
不可重载的运算符:
:: .* ?:
重载运算符后运算符的优先级不变,重载运算符的时候要多注意返回值类型,重载运算符是针对对类类型.
重载运算符其实跟正常的函数一样,请看例子
#include<iostream>
using namespace std;
class Integer{//定义一个整数类
private:
int data;
public:
Integer(int data){
this->data = data;
}
//现在想实现两个整数相加,正常的思路就是写个add函数
Integer add(Integer a){//这个函数很简单,传入一个整数对象,然后和调用这个add方法的对象相加,并返回一个Integer类类型的值
return Integer(data+a.data); //返回一个Integer类型的对象
}
void show(){//输出data
cout<<data<<endl;
}
};
int main(){
Integer a(1),b(2);//顶两个整数对象a,b
Integer c = a.add(b);//调用add方法,a和b相加的值赋给c
c.show();//输出c的值
return 0;
}
输出的结果毫无疑问是3,不信的同学可以复制代码试试,在没有运算符重载的时候要实现Integer类的相加,相减,相乘,相除,就得向上面一样,写个add函数,写个sub函数,写个muti函数,写个divi函数,来实现加减乘除
在Integer类中添加
Integer sub(Integer a){//减
return Integer(data-a.data);
}
Integer muti(Integer a){//乘
return Integer(data*a.data);
}
Integer divi(Integer a){//除
return Integer(data/a.data);
}
而且使用的时候得Integer对象点个add来用 就像b.add(c)这样,不仅看起来麻烦,而且也不够直白,所以有了运算符重载,就可以重写上面的方法了
添加运算符重载后的程序
#include<iostream>
using namespace std;
class Integer{//定义一个整数类
private:
int data;
public:
Integer(int data){
this->data = data;
}
//现在想实现两个整数相加,正常的思路就是写个add函数
Integer add(Integer a){//这个函数很简单,传入一个整数对象,然后和调用这个add方法的对象相加,并返回一个Integer类类型的值
return Integer(data+a.data); //通过Integer的构造函数,直接返回一个匿名的Integer类型的对象
}
Integer sub(Integer a){
return Integer(data-a.data);
}
Integer muti(Integer a){
return Integer(data*a.data);
}
Integer divi(Integer a){
return Integer(data/a.data);
}
//运算符重载 +号 其实operator+可以看成一个函数名,所以就等价于add函数
Integer operator + (Integer a){//格式还是 返回值类型 operator<运算符> (参数列表) 把operator<运算符>看出一个函数名的话,其实就跟add
//函数是一样的
return Integer(data+a.data);
}
//减号
Integer operator - (Integer a){
return Integer(data-a.data);
}
//乘号
Integer operator * (Integer a){
return Integer(data*a.data);
}
//除号
Integer operator / (Integer a){
return Integer(data/a.data);
}
void show(){//输出data
cout<<data<<endl;
}
};
int main(){
Integer a(1),b(2);//顶两个整数对象a,b
Integer c = a.add(b);//调用add方法,a和b相加的值赋给c
c.show();//输出c的值
//然后有运算符重载后就可以这么写
Integer d = a+b;//这个等价于 a.operator+(b),而operator+号就是个函数名,那么不就跟a.abb(b)一样呗
Integer e = a.operator +(b);
d.show();
e.show();
return 0;
}
d的结果和e的结果都是3,不信的同学可以复制代码试试,可以看到operator+()可以看出一个名字为operator+的函数,如果把名字换成add的话,不就跟add函数一样吗,引入运算符重载的目的就是为了简化程序,然后代码的可读性跟强,语义更清晰
按照这样运算符重载其实是很简单的东西,那么我们来重载一下==运算符,因为==是逻辑运算符,那么返回值类型肯定是bool的了,首先不用运算符重载的时候,得写个equal()方法来判断连个Integer对象是否相等
bool equal(Integer a){
return a.data == data;}
调用的时候就是if(a.equal(b))这样
如果用运算符重载呢,就重载==号
bool operator ==(Integer a){
return a.data == data;
}
调用的时候就是if(a==b)或者if(a.operator==(b))这样
以此类推其实很多运算符重载都是跟写函数一样的,写出友元函数也行
特别要注意的是重载>>号和<<号,在C++中是输入流和输出流,得写成友元函数,因为operator>>(),和operator<<()都不应该属于Integer类的方法,因为不可能这样a<< 即a.operator<<(),或a>> 即a.operator>>(),应该属于全局的函数然后cin>>a,cout<<a这样即operator>>(cin,a),operator<<(cout,a)来输入,所以得把operator<<(),和operator>>()写成友元函数,operator>>()有两个参数istream &in,和Integer &a,返回一个istream& 同理operator<<()也是一样,参数ostream&out,Integer &a 返回值类型为ostream& 所以代码如下
Integer类里面的友元函数:
friend ostream& operator <<(ostream & out,Integer &a);
friend istream& operator >>(istream& in ,Integer &a);
类外的实现:
ostream& operator <<(ostream& out,Integer &a){
out<<a.data;
return out;
}
istream& operator >>(istream& in ,Integer &a){
in>>a.data;
return in;
}
关于友元函数和引用及引用类型的返回值不会的自行百度
重载输入流输出流后的类,其对象就可以使用输入流输出流了,还记得上面输出Integer对象值的时候的show()方法吗,那个看起来不好看,重载输出流之后就这么写了 ,cout<<a<<endl,输入就是cin>>a;
所以运算符重载写起来就跟普通的函数一样,还要注意的是重载是针对类类型,只是函数名有点奇怪,调用的方式也有点奇怪而已,
再来具几个简单的例子:
重载个()号
void operator() (){
cout<<"重载了括号"<<endl;
}
调用的时候就是a()//相当于a.operator(); ,那么肯定输出"重载了括号",这里重载()有个应用,就是函数对象,感兴趣的童鞋可以自行白度一下
重载个[]号
void operator[](int i){
data+=i;
}
调用一下a[33],假设a之前是1的话,那么输出的a就会是34了,所以感觉是不是跟普通的函数差不多,所以有兴趣的童鞋可以试试重载一下其他的运算符
以上的完整例子代码:
#include<iostream>
#include<ostream>
#include<istream>
using namespace std;
class Integer{//定义一个整数类
private:
int data;
public:
Integer(int data){
this->data = data;
}
Integer(){
this->data = 0;
}
//现在想实现两个整数相加,正常的思路就是写个add函数
Integer add(Integer a){//这个函数很简单,传入一个整数对象,然后和调用这个add方法的对象相加,并返回一个Integer类类型的值
return Integer(data+a.data); //通过Integer的构造函数,直接返回一个匿名的Integer类型的对象
}
Integer sub(Integer a){
return Integer(data-a.data);
}
Integer muti(Integer a){
return Integer(data*a.data);
}
Integer divi(Integer a){
return Integer(data/a.data);
}
void show(){//输出data
cout<<data<<endl;
}
bool equal(Integer a){
return a.data == data;
}
//运算符重载 +号 其实operator+可以看成一个函数名,所以就等价于add函数
Integer operator + (Integer a){
return Integer(data+a.data);
}
//减号
Integer operator - (Integer a){
return Integer(data-a.data);
}
//乘号
Integer operator * (Integer a){
return Integer(data*a.data);
}
//除号
Integer operator / (Integer a){
return Integer(data/a.data);
}
bool operator ==(Integer a){
return a.data == data;
}
void operator() (){
cout<<"重载了括号"<<endl;
}
void operator[](int i){
data+=i;
}
friend ostream& operator <<(ostream & out,Integer &a);
friend istream& operator >>(istream& in ,Integer &a);
};
ostream& operator <<(ostream& out,Integer &a){
out<<a.data;
return out;
}
istream& operator >>(istream& in ,Integer &a){
in>>a.data;
return in;
}
int main(){
Integer a(1),b(2);//顶两个整数对象a,b
Integer c = a.add(b);//调用add方法,a和b相加的值赋给c
c.show();//输出c的值
//然后有运算符重载后就可以这么写
Integer d = a+b;//这个等价于 a.operator+(b),而operator+号就是个函数名,那么不就跟a.abb(b)一样呗
Integer e = a.operator +(b);
d.show();
e.show();
Integer f;
cin>>f;
cout<<f<<endl;
f();
f[22];
cout<<f<<endl;
return 0;
}