C++ 不变式
对于一个复数对象,有些条件我们期望是真的。
举例来说,如果笛卡尔坐标系的标志量被设置了,那么我们就期望real和imag的值是有效的,类似地,如果极坐标系的标志量被设置了,我们期望mag和theta也是有效的。最后,如果两个标志位都设置了的话,我们希望四个值是一致的,即他们应该是以不同的表示方式表示相同的一个复数。
这样的条件即为不变式,由于很显而易见的原因他们是不变的——他们总是应该为真。编写几乎没有bug的高质量代码就是要指出你的类中那些是不变式,并让改变他们成为不可能。
数据封装的好处之一就是帮助保证不变式。第一部是通过将变量变为私有从而阻止不受约束的访问。然后更改对象的唯一办法就是通过访问函数和更改器了。如果我们检查所所有的访问函数和更改器并发现他们都能保证不变式不变,那么我们就可以证明一个不变式是不会被篡改的了。
在Complex 类中,我们列出对变量进行赋值的函数:
第二个构造函数
calculateCartesian
calculatePolar
setCartesian
setPolar
在每一个函数中,很明显他们能保持上面提到的不变性。这里我们需要小心一些。注意到我说的是“保持”不变性。这就意味着,如果这个不变式为真,那么当这个函数被调用后仍然为真。
这样的定义允许了两处漏洞。首先在函数执行过程中可能有不变式为假的情况,这是没关系的,有些时候是不可避免的。只要不变式在函数执行之后恢复即可。
另外一处漏洞是如果在函数执行开始时不变式为真我们只需保持该不变性即可。如果开始执行时部位真,所有都是徒劳了。如果不变式在某处被更改了,我们能做的一般来说就是检测到出错,打印错误信息,然后退出。