The Vector class stores both the rectangular coordinates and the polar coordinates for a vector. It uses a member called mode
to control which form the constructor, the reset()
method, and the overloaded operator<<()
function use, with the enumerations RECT
representing the rectangular mode (the default) and POL
the polar mode. Such a member is termed a state member because it describes the state an object is in. To see what this means, look at the code for the constructor:
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
";
x = y = mag = ang = 0.0;
mode = RECT;
}
}
If the third argument is RECT
or if it is omitted (in which case the prototype assigns a default value of RECT
), the inputs are interpreted as rectangular coordinates, whereas a value of POL
causes them to be interpreted as polar coordinates:
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
The identifier POL
has class scope, so class definitions can just use the unqualified name. But the fully qualified name is VECTOR::Vector::POL
because POL
is defined in the Vector
class, and Vector
is defined in the VECTOR
namespace. Note that the constructor uses the private methods set_mag()
and set_ang()
to set the magnitude and angle values if you provide x and y values, and it uses the private set_x()
and set_y()
methods to set x and y values if you provide magnitude and angle values. Also note that the constructor delivers a warning message and sets the state to RECT
if something other than RECT
or POL
is specified.
Now it may seem rather difficult to sneak something other than RECT
or POL
to the constructor because the third argument is type VECTOR::Vector::Mode
. A call such as the following won’t compile because an integer like 2
can’t implicitly be converted to an enum
type:
Vector rector(20.0, 30.0, 2); // type mismatch - 2 not an enum type
Still, the resourceful and curious user could try something like the following to see what happens:
Vector rector(20.0, 30.0, VECTOR::Vector::Mode (2)); // type cast
In this case, he gets admonished.
Next, the operator<<()
function uses the mode to determine how values are displayed:
// 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;
}
Because operator<<()
is a friend function and not part of the class scope, it has to use Vector::RECT
instead of just RECT
. But it is in the VECTOR
namespace, so it doesn’t need to use the fully qualified name of VECTOR::Vector::RECT
.
The various methods that can set the mode are careful to accept only RECT
and POL
as valid values, so the final else
in this function should never be reached. Still, it’s often a good idea to check; such a check can help catch an otherwise obscure programming error.
3.133.134.151