在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&
因此,在设计类的时候,一定要考虑使用者是如何使用的。