运算符重载规则
我们平常使用普通的运算符的时候,都是系统为基本类型重载好的,因此可以直接用。
重载运算符的限制
- 一共大致有5个运算符不可以被重载
点,点星,作用域运算符,双冒号和问号组成的条件运算符,sizeof - 运算符被重载之后,它的优先级,结合性和操作数个数不变
重载运算符的语法形式
用成员或友元函数重载运算符
运算符函数可以重载为成员函数或友元函数,普通函数的话会增大程序的开销。
二者的关键区别在于成员函数具有 this 指针,友元函数没有this指针,这一区别也可以解释成员与友元在使用,书写方式上的不同。
但是不管是成员函数还是友元函数重载,在主函数里运算符的使用方法相同。
但传递参数的方式不同,实现代码不同,应用场合也不同。
- 一元运算符
重载为成员函数,解释为:
Object . operator op ()
操作数由对象Object通过this指针隐含传递
//这一块如果说不清楚this指针隐含传递,可以看后面的二元运算符和代码,这也是前面提到的成员函数和友元函数的关键区别的体现
重载为友元函数,解释为:
operator op (Object)
操作数由参数表的参数Object提供
- 二元运算符
重载为成员函数,解释为:
ObjectL . operator op ( ObjectR )
左操作数由ObjectL通过this指针传递,
右操作数由参数ObjectR传递,
重载为友元函数,解释为:
operator op ( ObjectL, ObjectR )
左右操作数都由参数传递
用成员函数重载
当一元运算符的操作数,或者二元运算符的左操作数
是类的对象时,定义重载算符函数为成员函数
TriCoor operator + ( TriCoor t )
{ TriCoor temp ;
temp.x = x+t.x ; temp.y = y+t.y ; temp.z = z+t.z ;
return temp ;
}
TriCoor operator = ( TriCoor t ) { x = t.x ; y = t.y ; z = t.z ; return * this ; }
TriCoor operator ++ () { x ++ ; y ++ ; z ++ ; return *this ; }
用友元函数重载
友元函数重载运算符常用于运算符的左右操作数类型不同的情况
Complex operator + ( Complex ) ;
…...
} ;
//在类外进行说明
Complex Complex:: operator + (complex )
{
}
int f ( )
{ Complex z ( 2 , 3 ) , k ( 3 , 4 ) ;
z = z + 27 ; //对,因为后面的27可以经过构造函数构造
z = 27 + z ; //错
因此可以由上面的例子得出,在第一个参数需要隐式转换的情形下,使用友元函数重载运算符是正确的选择。
友元函数没有 this 指针,所需操作数都必须在参数表显式声明,传递连个参数,很容易通过构造函数实现类型的隐式转换。
C++中不能用友元函数重载的运算符有
= () [] ->
友元不能重载它们的原因是它们只能对当前对象操作
,所以只能通过成员函数实现,因为友元函数没有this指针。
friend Complex operator+ ( const Complex & c1, const Complex & c2 ) ;
……
Complex operator + ( const Complex & c1, const Complex & c2 )
{ double r = c1.Real + c2.Real ;
double i = c1.Image+c2.Image ;
return Complex ( r, i ) ;
}
几个典型运算符的重载
重载++与–
自增与自减有前置和后置两种形式,C++作出规定,前置形式重载为一元运算符函数,后置形式重载为二元运算符函数。
参数0是一个伪值,是用于区分前置与后置的形式,友元函数的返回类型是引用的类类型(返回类类型的引用)是为了减少函数返回时对象复制的开销。
代码实现:
class obj
{
public:
friend obj operator ++ (obj & );
friend obj opetator ++ (obj &,int);//伪参数用以区分
int value;
}
obj operator ++ (obj & a)//前置
{
a.value++;
return a;
}
obj operator ++ (obj & a,int)
{
obj temp(a);//复制构造函数,,以temp保存对象a的原值作为函数的返回值
a.value++;
return temp;
}
不能随便使用伪参数,会引发调用的二义性(现在还是不甚了解)
用成员函数写后置加加
obj obj:: operator ++ (int x)
{
obj temp;
temp.value=value;
value+=x;
return temp;
}
重载赋值运算符
重载运算符[]和()
重载流插入和流提取运算符
(只有友元可以做到)
重载常用集大成
#include<iostream>
using namespace std;
class complex
{
double a;
double b;
public:
complex(double m = 0, double n = 0)//构造函数
{
a = m;
b = n;
}
friend complex operator+( complex& c1, complex& c2);//友元函数重载+
friend complex operator-(complex &c1, complex &c2);//友元函数重载-
friend istream& operator>>(istream& input, complex& c);//友元函数重载>>,输入格式参考样例输入
friend ostream& operator<<(ostream& output, complex& c);//友元函数重载<<,输出格式参考样例输出
complex operator++();//成员函数重载前++
complex operator++(int);//成员函数重载后++
friend complex operator--(complex& c);//友元函数重载前--
friend complex operator--(complex& c, int);//友元函数重载后--
};
istream& operator>>(istream& input, complex& c)
{
input >> c.a >> c.b;
return input;
}
ostream& operator<<(ostream& output, complex& c)
{
output << "(" << c.a << "," << c.b << ")" << endl;
return output;
}
complex operator +(complex& c1, complex& c2)
{
complex c3;
c3.a = c1.a + c2.a;
c3.b = c1.b + c2.b;
return c3;
}
complex operator -(complex& c1, complex& c2)
{
complex c3;
c3.a = c1.a - c2.a;
c3.b = c1.b - c2.b;
return c3;
}
complex complex:: operator ++()
{
a++;
return *this;
}
complex complex:: operator++(int)
{
complex temp;
temp.a = a;
temp.b = b;
a++;
return temp;
}
complex operator--(complex& c)
{
c.a--;
return c;
}
complex operator--(complex& c, int)
{
complex temp(c);
c.a--;
return temp;
}
int main()
{
int i;
complex c1, c2, c3;
cin >> c1 >> c2;
c3 = c1 + c2;
cout << c3;
c3 = c1 - c2;
cout << c3;
for (i = 1; i <= 3; i++)
c3 = c1++;
cout << c1 << c3;
for (i = 1; i <= 3; i++)
c3 = c2--;
cout << c2 << c3;
c3 = ++c1;
cout << c1 << c3;
c3 = --c2;
cout << c2 << c3;
}
//思考题:
//operator+,operator - ,operator++,operator--函数的返回值类型可以改为引用(complex & )吗?为什么?
//输入
//分别输入c1和c2
//
//输出
//输出运算结果
//
//样例输入
//10
//20
//30
//40
//样例输出
//(40, 60)
//(-20, -20)
//(13, 20)
//(12, 20)
//(27, 40)
//(28, 40)
//(14, 20)
//(14, 20)
//(26, 40)
//(26, 40)