14.3 复数
本章后面的部分讲述复数这样一个例子。复数在数学和工程领域很有用途,许多计算用到了复数。一个复数是实部和虚部之和,记作x+yi,x为实部,y为虚部,i是-1的平方根。
以下为类Complex的定义:
class Complex
{
double real, imag;
public:
Complex () { }
Complex (double r, double i) { real = r; imag = i; }
};
在类的定义中,实部和虚部是私有的,构造函数是公有的,故加上public标号。
一般使用这样两个构造函数:一个没有参数也不做什么工作的构造函数,另一个有两个参数来用来初始化变量。
到现在为止,还看不到将变量私有化的明显优点。让我们把程序复杂一点,就能看到了。
对于复数,通常会有另外一种表达方式叫做基于极坐标系的极坐标表示。跟用复数域上的点的特定位置表示实部虚部不同,极坐标系中用离开原点的距离(或模)和偏离原点的方向(或角度)来表示。
下图表示两个坐标系系统。
在极坐标系中,复数记作reiθ ,其中r是模(半径),θ是用弧度表示的角度。
幸运的是,很容易从两个坐标系中进行转换。
从笛卡尔到极坐标系:
r = x2 + y2
θ = arctan(y/x)
从极坐标系到笛卡尔坐标系:
x = r cos θ
y = r sin θ
那么我们应该使用哪一种表达方式呢?因为有些操作在笛卡尔坐标系中简单些,如加法;而另一些操作在极坐标系中简单些,如乘法。所以一个办法是我们写一个使用两种表达方式的类,让他们根据需要可以自动转换。
class Complex
{
double real, imag;
double mag, theta;
bool cartesian, polar;
public:
Complex () { cartesian = false; polar = false; }
Complex (double r, double i)
{
real = r; imag = i;
cartesian = true; polar = false;
}
};
在这个类中有6个变量,这就意味着这样会比之前的任何一种占用的空间都要多。不过我们很快就会看到这样做是很有用的。
其中四个变量可以根据名字判断他们的意思,分别是一个复数的实部,虚部,角度,半径。另外两个变量cartesian和polar则是表示对应坐标系的值是否有效的标志。
举例来说,啥都不做的这个构造函数将两个标志量设置为false表明该对象无论哪种表达方式,都还不是有效的复数。
第二个构造函数使用参数来初始化实部和虚部,但不会计算模或角度。并会把极坐标的标志位置为false来警告其他函数不应当访问模或角度值,直到他们被设置为正确的值。
现在应该清楚为何将变量置为私有了吧。如果一个客户程序被允许不受限制的访问,读取了未初始化的值就很容易导致出错。在下一部分,我们将添加一些访问函数来避免这种错误。