Using a State Member

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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.163.62