18.5 Full Definition of the Fixed-Point Class

I l @ ve RuBoard

Example 18-2 and Example 18-3 list the entire fixed-point class. The beginning of the header file summarizes all the functions that are defined. In creating this class, I discovered that it consisted of many (29 to be exact) little one- and two-line functions. Commenting each of these with a full-function comment block would obscure the code. In other words, this is one of the few cases (the very few) where adding comments would cause confusion, so most of the small functions have no comments.

When creating this class, I noticed that a lot of the functions have a similar structure. For example, += looks a lot like -= and so on. As a matter of fact, I created the -= operator by copying the += functions and editing a little. C++ contains a rich operator set that causes this sort of repetition to happen when you're trying to define a complete set of operators for a class.

Finally, the simple operations are defined in the file fixed_pt.h ( Example 18-2) while the longer functions are left in the file fixed_pt.cpp ( Example 18-3). Finally, we've included a limited unit test in fixed_test.cpp (Example 18-4).

Example 18-2. fixed_pt/fixed_pt.h
 #ifndef _  _fixed_pt_h_  _  // Avoid double includes #define _  _fixed_pt_h_  _  // Prevent double include #include <iostream> #include <assert.h> #include <stdlib.h> namespace fixed_pt { /* Note: This should be made into a template so that multiple  * fixed points may be used, but the purpose of this class  * is to teach operator overloading and templates would be a  * needless complication.  */ const int fixed_exp = 100;      // 10**fixed_point */ /* Fudge factor to make doubles into fixed point numbers */ const double fixed_fudge_factor = 0.0001;  /********************************************************  * Fixed point class                                    *  *                                                      *  * Members defined                                      *  *      fixed_pt(  )            // Default constructor  *  *      fixed_pt(double)        // Specify an inital   *  *                              // value                *  *      fixed_pt(fixed_pt)      // Copy constructor     *  *                                                      *  *      set(double)             // Set the value        *  *      double get(  );         // Return the value     *  *                              // as a double          *  *                                                      *  * Operator member functions                            *  *                      f -- a fixed_pt number          *  *                      s -- a scalar (double)          *  *      f = f                                           *  *      f += f;                                         *  *      f += s;                                         *  *      f -= f;                                         *  *      f -= s;                                         *  *      f /= f;                                         *  *      f /= s;                                         *  *      f *= f;                                         *  *      f *= s;                                         *  *      f++                                             *  *      ++f                                             *  *      f--                                             *  *      --f                                             *  *                                                      *  * Arithmetic operators defined                         *  *      f = f + f;                                      *  *      f = s + f;                                      *  *      f = f + s;                                      *  *      f = f - f;                                      *  *      f = s - f;                                      *  *      f = f - s;                                      *  *      f = f * f;                                      *  *      f = s * f;                                      *  *      f = f * s;                                      *  *      f = f / f;                                      *  *      f = s / f;                                      *  *      f = f / s;                                      *  *      -f                                              *  *      +f                                              *  *      ostream << f    // Output function              *  *      istream >> f    // Input function               *  ********************************************************/ class fixed_pt {     private:         long int value; // Value of our fixed point number         static long int double_to_fp(const double the_double) {             return (                 static_cast<long int>(                     the_double *                     static_cast<double>(fixed_exp) +                     fixed_fudge_factor));         }     public:         // Default constructor, zero everything         fixed_pt(  ): value(0) { }         // Copy constructor         fixed_pt(const fixed_pt& other_fixed_pt) :             value(other_fixed_pt.value)         { }                      // Construct a fixed_pt out of a double         fixed_pt(const double init_real) :             value(double_to_fp(init_real))         {}         // Destructor does nothing         ~fixed_pt(  ) {}         // Function to set the number         void set(const double real) {             value = double_to_fp(real);                              }         // Function to return the value         double get(  ) const {             return (static_cast<double>(value) / fixed_exp);         }         // Note: Because of the way we store internal data         // we do not have to check for self assignment         fixed_pt operator = (const fixed_pt& oper2) {            value = oper2.value;            return (*this);         }         fixed_pt& operator += (const fixed_pt& oper2) {            value += oper2.value;            return (*this);         }         fixed_pt& operator += (double oper2) {            value += double_to_fp(oper2);            return (*this);         }         fixed_pt& operator -= (const fixed_pt& oper2) {            value -= oper2.value;            return (*this);         }         fixed_pt& operator -= (double oper2) {            value -= double_to_fp(oper2);            return (*this);         }         fixed_pt& operator *= (const fixed_pt& oper2) {            value *= oper2.value;            value /= fixed_exp;            return *this;          }         fixed_pt& operator *= (double oper2) {            value *= double_to_fp(oper2);            value /= fixed_exp;            return (*this);         }         fixed_pt& operator /= (const fixed_pt& oper2) {             assert(oper2.value != 0.0);             value /= oper2.value;             value *= fixed_exp;         }         fixed_pt& operator /= (double oper2) {             assert(double_to_fp(oper2) != 0.0);             value /= double_to_fp(oper2);             value *= fixed_exp;             return (*this);         }         // f++         fixed_pt operator ++(int) {            fixed_pt result(*this);            value += fixed_exp;            return (result);         }         // ++f         fixed_pt& operator ++(  ) {            value += fixed_exp;            return (*this);         }         // f--         fixed_pt operator --(int) {            fixed_pt result(*this);            value -= fixed_exp;            return (result);         }         // --f         fixed_pt& operator --(  ) {            value -= fixed_exp;            return (*this);         }     private:         // Used for internal conversions for our friends         fixed_pt(const long int i_value) : value(i_value){}     friend fixed_pt operator + (const fixed_pt& oper1, const fixed_pt& oper2);     friend fixed_pt operator + (const fixed_pt& oper1, const double oper2);     friend fixed_pt operator + (const double oper1, const fixed_pt& oper2);     friend fixed_pt operator - (const fixed_pt& oper1, const fixed_pt& oper2);     friend fixed_pt operator - (const fixed_pt& oper1, const double oper2);     friend fixed_pt operator - (double oper1, const fixed_pt& oper2);     friend fixed_pt operator * (const fixed_pt& oper1, const fixed_pt& oper2);     friend fixed_pt operator * (const fixed_pt& oper1, const double oper2);     friend fixed_pt operator * (double oper1, const fixed_pt& oper2);     friend fixed_pt operator / (const fixed_pt& oper1, const fixed_pt& oper2);     friend fixed_pt operator / (const fixed_pt& oper1, const double oper2);     friend fixed_pt operator / (const double& oper1, const fixed_pt& oper2);     friend bool operator == (const fixed_pt& oper1, const fixed_pt& oper2);     friend fixed_pt operator - (const fixed_pt& oper1);     friend std::ostream& operator << (std::ostream& out_file, const fixed_pt& number);     friend std::istream& operator >> (std::istream& in_file, fixed_pt& number); }; inline fixed_pt operator + (const fixed_pt& oper1, const fixed_pt& oper2) {   return fixed_pt(oper1.value + oper2.value); } inline fixed_pt operator + (const fixed_pt& oper1, const double oper2) {   return fixed_pt(oper1.value + fixed_pt::double_to_fp(oper2)); } inline fixed_pt operator + (double oper1, const fixed_pt& oper2) {   return fixed_pt(fixed_pt::double_to_fp(oper1) + oper2.value); } inline fixed_pt operator - (const fixed_pt& oper1, const fixed_pt& oper2) {   return fixed_pt(oper1.value - oper2.value); } inline fixed_pt operator - (const fixed_pt& oper1, const double oper2) {   return fixed_pt(oper1.value - fixed_pt::double_to_fp(oper2)); } inline fixed_pt operator - (double oper1, const fixed_pt& oper2) {   return fixed_pt(fixed_pt::double_to_fp(oper1) - oper2.value); } inline fixed_pt operator * (const fixed_pt& oper1, const fixed_pt& oper2) {     return fixed_pt(oper1.value * oper2.value / fixed_exp); } inline fixed_pt operator * (const fixed_pt& oper1, const double oper2) {     return fixed_pt(oper1.value * fixed_pt::double_to_fp(oper2) / fixed_exp); } inline fixed_pt operator * (const double oper1, const fixed_pt& oper2) {     return fixed_pt(fixed_pt::double_to_fp(oper1) * oper2.value / fixed_exp); } inline fixed_pt operator / (const fixed_pt& oper1, const fixed_pt& oper2)  {     assert(oper2.value != 0);     return fixed_pt((oper1.value * fixed_exp) / oper2.value); } inline fixed_pt operator / (const double& oper1, const fixed_pt& oper2)  {     assert(oper2.value != 0);     return fixed_pt((fixed_pt::double_to_fp(oper1) * fixed_exp) / oper2.value); } inline fixed_pt operator / (const fixed_pt& oper1, const double oper2)  {     assert(oper2 != 0);     return fixed_pt((oper1.value  * fixed_exp) / fixed_pt::double_to_fp(oper2)); } inline bool operator == (const fixed_pt& oper1, const fixed_pt& oper2) {     return (oper1.value == oper2.value); } inline bool operator != (const fixed_pt& oper1, const fixed_pt& oper2) {     return (!(oper1 == oper2)); } inline fixed_pt operator - (const fixed_pt& oper1) {     return fixed_pt(-oper1.value); } inline fixed_pt operator + (const fixed_pt& oper1) {     return fixed_pt(oper1); } inline std::ostream& operator << (std::ostream& out_file, const fixed_pt& number) {     long int before_dp = number.value / fixed_exp;     long int after_dp1  = abs(number.value % fixed_exp);     long int after_dp2  = after_dp1 % 10;     after_dp1 /= 10;     out_file << before_dp << '.' << after_dp1 << after_dp2;     return (out_file); } extern std::istream& operator >> (std::istream& in_file, fixed_pt& number); } #endif /* _  _fixed_pt_h_  _ */     // Avoid double includes 
Example 18-3. fixed_pt/fixed_pt.cpp
 #include <iostream> #include "fixed_pt.h" #include "ctype.h" namespace fixed_pt { /********************************************************  * istream >> fixed_pt -- read a fixed_pt number        *  *                                                      *  * Parameters                                           *  *      in_file -- file to read                         *  *      number -- place to put the number               *  *                                                      *  * Returns                                              *  *      reference to the input file                     *  ********************************************************/ std::istream& operator >> (std::istream& in_file, fixed_pt& number) {     long int before_dp; // Part before decimal point (dp)     char after_dp1, after_dp2;  // Part after decimal point (dp)     char ch;            // Random character used to verify input     number = 0.0;       // Initialize the number (just in case)     // We only work for 2 digit fixed point numbers     assert(fixed_exp == 100);     // Sentry to protect the I/O     std::istream::sentry the_sentry(in_file, true);          if (the_sentry)     {         if (in_file.bad(  )) return (in_file);             // Get the number that follows the whitespace         in_file >> before_dp;         if (in_file.bad(  )) return (in_file);         in_file >> ch;  // Get first character after number         if (in_file.bad(  )) return (in_file);         // Expect a decimal point         if (ch != '.') {            in_file.setstate(std::ios::failbit);            return (in_file);         }         in_file >> after_dp1 >> after_dp2;         if (in_file.bad(  )) return (in_file);         // Check result for validity         if ((!isdigit(after_dp1))  (!isdigit(after_dp2))) {            in_file.setstate(std::ios::failbit);            return (in_file);         }         // Todo make after db two digits exact         number.value = before_dp * fixed_exp +             (after_dp1 - '0') * 10 +             (after_dp2 - '0');     }     else     {        in_file.setstate(std::ios::failbit);     }    return (in_file); } } 
Example 18-4. fixed_pt/fixed_test.cpp
 #include <iostream> #include "fixed_pt.h" int main(  ) {     std::cout << "Expect 1.23 " << fixed_pt::fixed_pt(1.23) << std::endl;     std::cout << "Expect 1.00 " << fixed_pt::fixed_pt(1.00) << std::endl;     std::cout << "Expect 1.02 " << fixed_pt::fixed_pt(1.02) << std::endl;     std::cout << "Expect 1.20 " << fixed_pt::fixed_pt(1.20) << std::endl;     fixed_pt::fixed_pt f3 = 1.23;     std::cout << "Expect 1.23 " << f3 << std::endl;     fixed_pt::fixed_pt f1(1.23 + 0.005);     fixed_pt::fixed_pt f2(4.56 + 0.005);     std::cout << f1 << " + " << f2 << " = " << f1 + f2 << std::endl;     std::cout << f1 << " - " << f2 << " = " << f1 - f2 << std::endl;     std::cout << f1 << " * " << f2 << " = " << f1 * f2 << std::endl;     std::cout << f1 << " / " << f2 << " = " << f1 / f2 << std::endl;     return (0); } 

Question 18-1: Why does Example 18-5 fail? When run it prints out:

 Copy constructor called Copy constructor called 

over and over. Hint: Review Section 13.4.4. Thanks to Jeff Hewett for this problem.

Example 18-5. equal/equal.cpp
 #include <iostream> class trouble {     public:         int data;         trouble(  );         trouble(const trouble& old);         trouble operator = (const trouble old_trouble); }; trouble::trouble(  ) {    data = 0; } trouble::trouble(const trouble& old) {     std::cout << "Copy constructor called\n";     *this = old; } trouble trouble::operator = (const trouble old_trouble) {     std::cout << "Operator = called\n";     data = old_trouble.data;     return (*this); } int main(  ) {     trouble trouble1;     trouble trouble2(trouble1);     return (0); } 
I l @ ve RuBoard


Practical C++ Programming
Practical C Programming, 3rd Edition
ISBN: 1565923065
EAN: 2147483647
Year: 2003
Pages: 364

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net