一、基本定义
1、C++预定义的运算符只能用于基本数据类型的运算:整型、实型、字符型、逻辑型,但是不能作用于对象之间。
2、运算符重载的目的是扩展C++中提供的运算符的适用范围,使之能作用于对象。
3、运算符重载的实质是函数重载,可以重载为普通成员函数,也可以重载为成员函数。
4、根据实参的类型决定调用哪个运算符函数。
二、运算符重载的基本形式
不管什么样的,返回值是什么(除掉返回值是bool类型),最好是都加上&符号,如果返回的是一个临时变量的话,也就是在重载里面自己定义了一个变量的话,这个时候最好不加&符号。
返回值类型& operator 运算符(形参表)
{
}
或者
返回值类型 operator 运算符(形参表)
{
}
1、只有==、>、<这三个的返回值一定是是bool类型,其余的[]等返回值类型要根据题意自己定
2、如果作用的是同一个类型的话重载为成员函数就好,如果有不同类型的话,则必须用friend,定义为友元函数。
3、一般()里面包括:类名& 名称;&号千万别忘记;
三、运算符目数
(1)、单目:只需要一个操作的意思,例如:++a --a a &a
(2)、双目:需要两个操作数的意思 例如: a++ a-- a+b a-b ab a/b a%b
(3)、三目:是需要三个操作数的意思 比如 a=c>b?c:b;
四、详解
重载为成员函数时,参数个数为运算符目数减一;
重载为普通函数时,参数个数为运算符目数;
五、注意事项
1、c++不允许定义新的运算符
2、重载后运算符的含义应该符合日常习惯
3、运算符重载不改变运算符优先级
4、”.” “.*” “::” “?:” sizeof
5、重载运算符()[] -> =的时候运算符重载函数必须声明为类的成员函数
6、作为参数传递的时候括号内最好加&,例如Time operator(const Time& p)
7、如果返回的是临时变量,最前面最好不要加&,例如Time& operator(const Time& p)
最前面Time后面的&最好去掉。
8、如果返回引用的话也就是加&那么返回的是一个变量,但是若返回的是一个常量,则不能加&符号,例如int operator+(const Point& p){retrun p.x+x;)//这里就不能加引用&,因为返回的是一个常量,而不是一个变量;
六、各种重载运算符
1、前自增运算符重载(单目)
class Time
{
private:
int _h,_m,_s;
public:
Time& operator++()
{
return *this;
}
};
2、前自减运算符(单目)
class Time
{
private:
int _h,_m,_s;
public:
Time& operator--()
{
return *this;
}
};
3、后自增运算符(双目)
class Time
{
private:
int _h,_m,_s;
public:
Time operator++(int)
{
Time old(*this);
return old;
}
};
4、后自减运算符(双目)
class Time
{
private:
int _h,_m,_s;
public:
Time operator--(int)
{
Time old(*this);
return old;
}
};
5、重载输出运算符重载输出运算符的时候,必须写上const
class Time
{
private:
int _h,_m,_s;
public:
friend ostream& operator<<(ostream& os,const Time& p)//别忘了是友元;
{
os<<p._h<<p._m<<p._s;//注意这里千万别忘了p.
return os;//注意别忘了return;
}
};
这里注意,有时候要在Time& p
前面加const,也就是const Time& p
,例如:
Time i;
cin>>i;
cout<<i++<<endl;//这里要加const;
cout<<(++i)<<endl;//这里不用加const;
cout<<(--i)<<endl;//这里不用加const;
cout<<(i--)<<endl;//这里要加const;
因为++i和–i返回的是引用,i++和i–返回的是常量,如果一个常量返回的是引用的话,可以不加const,但是如果返回的不是引用的话必须加const。
6、重载输入运算符
class Time
{
private:
int _h,_m,_s;
public:
friend istream& operator>>(istream& is,Time& p)//别忘了是友元函数;
{
is>>p._h>>p._m>>p._s;//注意这里千万别忘了p.
return is;//注意别忘了return;
}
};
7、重载赋值运算符
(1)形式
X &operator = (const X &p)
{
x_=p.x_;
y_=p.y_;
return *this;//一个函数是引用类的话返回的实际上是一个地址。详细见引用篇;
}
例如:
Point& operator=(const Point &p)
{
x_=p.x_;//这个必须要有;等价于this->x_=p.x_;
y_=p.y_;
return *this;
}
注意一旦return *this
的时候,函数应当为引用类型;
class Time
{
private:
int _h,_m,_s;
public:
Time& operator=(const Time& p)
{
_h=p._h,_m=p._m;_s=p._s;
return *this;//一定不要忘记return* this;
}
};
(2)其实是可以有多个参数的,若有多个参数,则要求除了第一个参数以外其余参数都要有默认值,第一个参数必须是自身类型的引用,这个参数一般是const类型的,但不是必须的。
8、重载>运算符
class Student
{
bool operator>(const Student& p)
{
if(score>p.score)
return true;
else if(score==p.score&&name<p.name)
return true;
else return false;
}
};
9、重载==运算符
class Array
{
bool operator==(const Array& p)
{
if(this==&p)
return true;
else if(length==p.length)
{
int i;
for(i=0;i<length;i++)
{
if(mems[i]!=p.mems[i])
break;
}
if(i==length)
return true;
else
return false;
}
else return false;
}
};
10、类型转换运算符的重载
1、任何类型的名字本身就是一个类型转换运算符;
2、形式:operator double();不能多写,同时也不能少写;
3、例如:
#include <iostream>
using namespace std;
class Complex
{
double real,imag;
public:
Complex (double r=0,double i=0):real(r),imag(i){}
operator double(){return real;}//重载强制运算符double;
};
int main()
{
Complex c(1.2,3.4);
cout<<(double)c<<endl;//输出1.2;
double n=2+c;//没有对+进行重载,是因为c可以强制转换为double类,int类和double类是可以相加的;等价于double n=2+c.operator double();
cout<<n;//输出3.2;
return 0;
}
七、例如
#include <iostream>
using namespace std;
class Complex
{
public:
double real,imag;
Complex(double r=0.0,double i=0.0):real(r),imag(i){}
Complex operator -(const Complex &c);
};
Complex operator+(const Complex &a,const Complex& b)
{
return Complex(a.real+b.real,a.imag+b.imag);//返回临时对象,写法是一个类的构造函数后面直接跟一个参数表,我们会得到一个临时对象,这个对象没有名字,所以我们得到的是一个临时对象,。
}
Complex Complex::operator-(const Complex &c)
{
return Complex(real-c.real,imag-c.imag);//临时对象的形式是 类名+括号+参数表;
}
int main()
{
Complex a(4,4),b(1,1),c;
c=a+b;//等价于c=operator+(a,b);
cout<<c.real<<","<<c.imag<<endl;
cout<<(a-b).real<<","<<(a-b).imag<<endl;//a-b等价于a.operator-(b);
return 0;
}