12-使用状态成员
11.5.1 使用状态成员
Vector类储存了矢量的直角坐标和极坐标。它使用名为mode的成员来控制使用构造函数、reset()方法和重载的operator<<()函数使用哪种形式,其中枚举RECT表示直角坐标模式(默认值)、POL表示极坐标模式。这样的成员被称为状态成员(state member),因为这种成员描述的是对象所处的状态。要知道具体含义,请看构造函数的代码:
Vector::Vector(double n1, double n2, Mode form)
{
mode = form;
if (form == RECT)
{
x = n1;
y = n2;
set_mag();
set_ang();
}
else if (form == POL)
{
mag = n1;
ang = n2 / Rad_to_deg;
set_x();
set_y();
}
else
{
cout << "Incorrect 3rd argument to Vector() -- ";
cout << "vector set to 0\n";
x = y = mag = ang = 0.0;
mode = RECT;
}
}
如果第三个参数是RECT或省略了(原型将默认值设置为RECT),则将输入解释为直角坐标;如果为POL,则将输入解释为极坐标:
Vector folly(3.0, 4.0); // set x = 3, y = 4
Vector foolery(20.0, 30.0, VECTOR::Vector::POL); // set mag = 20, ang = 30
标识符POL的作用域为类,因此类定义可使用未限定的名称。但全限定名为VECTOR::Vector::POL,因为POL是在Vector类中定义的,而Vector是在名称空间VECTOR中定义的。注意,如果用户提供的是x值和y值,则构造函数将使用私有方法set_mag()和set_ang()来设置距离和角度值;如果提供的是距离和角度值,则构造函数将使用set_x()和set_y()方法来设置x值和y值。另外,如果用户指定的不是RECT或POL,则构造函数将显示一条警告消息,并将状态设置为RECT。
看起来好像难以将RECT和POL外的其他值传递给构造函数,因为第三个参数的类型为VECTOR::Vector::Mode。像下面这样的调用无法通过编译,因为诸如2等整数不能隐式地转换为枚举类型:
Vector rector(20.0, 30.0, 2); // type mismatch - 2 not an enum type
然而,机智而好奇的用户可尝试下面这样的代码,看看结果如何:
Vector rector(20.0, 30.0, VECTOR::Vector::Mode (1)); // type cast
就这里而言,编译器将发出警告。
接下来,operator<<()函数也使用模式来确定如何显示值:
// display rectangular coordinates if mode is RECT,
// else display polar coordinates if mode is POL
std::ostream & operator<<(std::ostream & os, const Vector & v)
{
if (v.mode == Vector::RECT)
os << "(x,y) = (" << v.x << ", " << v.y << ")";
else if (v.mode == Vector::POL)
{
os << "(m,a) = (" << v.mag << ", "
<< v.ang * Rad_to_deg << ")";
}
else
os << "Vector object mode is invalid";
return os;
}
由于operator<<()是一个友元函数,而不在类作用域内,因此必须使用Vector::RECT,而不能使用RECT。但这个友元函数在名称空间VECTOR中,因此无需使用全限定名VECTOR:: Vector::RECT。
设置模式的各种方法只接受RECT和POL为合法值,因此该函数中的else永远不会执行。但进行检查还是一个不错的主意,它有助于捕获难以发现的编程错误。
多种表示方式和类
可以用不同但等价的方式表示的量很常见。例如,可以按每加仑汽油消耗汽车能行驶的英里数来计算油耗(美国),也可以按每100公里消耗多少公升汽油来计算(欧洲)。可以用字符串表示数字,也可以用数值方式表示,可以使用IQ或kiloturkey的方法表示智商。类非常适于在一个对象中表示实体的不同方面。首先在一个对象中存储多种表示方式;然后,编写这样的类函数,以便给一种表示方式赋值时,将自动给其他表示方式赋值。例如,Vector类的set_by_polar()方法将mag和ang成员设置为函数参数的值,并同时设置成员x和y。也可存储一种表示方式,并使用方法来提供其他表示方式。通过在内部处理转换,类允许从本质(而不是表示方式)上来看待一个量。