第五节 操作符与运算符重载
在C++中,操作符本身就是一种函数,是可以让使用者自定义的。那么我们认为复数的计算,不如直接用+号来使用,而+号的概念和运算规则需要进行运算符重载。
操作符重载根据成员函数的区别有两种写法:
inline complex&
complex::operator += (const complex& r)
{
return _doapl (this, r);
}
inline complex& //这后面写的是接收者将以怎样的形式得到返回值。
complex::operator +=(this,const comp)
{
return _doapl (this, r);
}
在复数的class里面,定义出来一个操作符重载的成员函数。
所有的成员函数都带着一个隐藏的参数,这个参数叫this。谁调用这个函数的本身,调用者,就是this。this可以看作被操作的一个类的元素,指向被操作的类元素的地址。
第二种写的,this可以放在前面可以放在后面。
另外,this不能在参数列写出来,可是能够在函数里面用。
所有的二元运算符,都可以将右边的元素加到左边去,然后左边的类有一个this的指针可以完成传址调用。
关于return by reference的语法分析:
传递者无需知道接收者是以reference形式接收。
第一种,成员函数的版本:
inline complex& //这里指接收端是以reference的方式接受
_doapl(complex* ths, const complex& r)
{
...
return *ths;
}
这里传入者直到传入数据的形式是引用reference,而返回值的类型是*ths的一个解引用形式。
事实上,如果只用+=赋值,那么可以写成inline void...而实际上会涉及到一些奇怪的写法,如:
c1 += c2 += c3;则需要有具体的返回数据,写成inline complex&标准。
第二种:非成员函数的版本:
inline double
real(const complex& x)
{
return x.real();
}
inline double
imag(const complex& x)
{
return x.imag();
}
inline complex
operator + (const complex& x , const complex& y)
{
return complex(real(x) + real(y), imag(x) + imag(y));
}
inline complex
operator + (const complex& x, double y)
{
return complex(real(x) + y,imag(x));
}
inline complex
operator + (double x , const complex& y)
{
return complex(real(y) + x , imag(y));
}
+号有三种应对方式。可能复数+复数,复数+实数,实数+复数....
临时对象(temp object)
上述函数返回的并不是reference,因为,他们返回的必定是个local object.产生的是一个临时局部变量,所以不能用引用来实现。
typename() 类直接加小括号,类似于变量的声明,相当于根据后续的数据创建临时对象。
complex (a , b) 创建临时的复数变量a + bi ,临时变量的生命只存在于下一行。
class body之外的各种定义:
inline complex
operator + (const complex& x)
{
return x;
}
inline complex
operator - (const complex& x)
{
return complex(-real(x) , -imag(x));
}
这两个符号是取反、取正的符号,定义的是一元运算符。靠参数的个数区别二元操作符+
而取正是本身,取反会创建一个新的对象,所以取负操作必须传递一个value。
inline bool
operator == (const complex& x, const complex& y)
{
return (x.real() == y.real()) && (x.imag() == y.imag());
}
inline bool
operator == (const complex& x,double y)
{
return (x.imag() == 0) && (x.real() == y);
}
inline bool
operator == (double x, const complex& y)
{
return (x == y.real()) && (y.real() == 0);
}
这是比较两个复数是否相等,需要考虑所有的情况。
inline complex
conj (const complex& x)
{
return complex(real(x), -imag(x));
}
共轭复数。实部相等虚部相反。
#include <iostream.h>
ostream&
operator << (ostream& os,const complex& x)
{
return os << '(' << real(x) << ',' << imag(x) << ')';
}
complex c1(2,1);
cout << conj(c1);
而在输出的时候,同样需要重载左移运算符。由于左值运算,而cout对应的类为ostream,u送一我们需要提供ostream的引用os。然后才可以进行输出。同样的,在对os左移的时候,实际上改变了这个输出流,所以不需要加const来修饰。
不可以将osteram&改为void,因为可能会遇到连续左移的操作,在输出一个变量的时候,还是需要维护一个ostream类。所以返回类型应当是ostream&
因此,在设计类的时候,一定要考虑使用者是如何使用的。