// This ensures that this file is included at most once // in any program, as there may be multiple include // statements. #pragma once #include #include /////////////////////// // Class declaration // /////////////////////// class Rational; /////////////////////////// // Function declarations // /////////////////////////// // This example extends the previous Rational project by // introducing operator overloading. // // Most of the functions and the Rational class itself are // the same as in the previous project. Refer to that project // for a discussion of rational arithmetic, comparisons, // inverses, absolute values, and the use of const references. // // The focus of this project is operator overloading. C++ // allows us to define the behavior of many operators when // they are applied to objects of a class such as Rational. // // For example, instead of writing // // add( p, q ) // // as in the previous project, we can overload operator+ // so that we can write // // p + q // // instead. The expression is translated into a call to // // operator+( p, q ) // // by the compiler. // // Operator overloading does not create new operators or // change their precedence or associativity. It defines what // an existing C++ operator does when applied to objects of // the specified types. ////////////////////////// // Arithmetic operators // ////////////////////////// // Calculate p + q, instead of using add( p, q ). // // The additional overloads allow either operand to be an // integer where appropriate. Rational operator+( Rational const &p, Rational const &q ); Rational operator+( Rational const &p, int const n ); Rational operator+( int const n, Rational const &q ); // Calculate p - q, instead of using sub( p, q ). Rational operator-( Rational const &p, Rational const &q ); Rational operator-( Rational const &p, int const n ); Rational operator-( int const n, Rational const &q ); // Calculate p*q, instead of using mul( p, q ). Rational operator*( Rational const &p, Rational const &q ); Rational operator*( Rational const &p, int const n ); Rational operator*( int const n, Rational const &q ); // Calculate p/q, instead of using div( p, q ). // // The divisor must be non-zero. Rational operator/( Rational const &p, Rational const &q ); Rational operator/( Rational const &p, int const n ); Rational operator/( int const n, Rational const &p ); ////////////////////// // Unary operators // ////////////////////// // Return p unchanged. // - Here + is a unary operator: it has only one operand. // - This is analogous to applying unary + to a number. Rational operator+( Rational const &p ); // Return the additive inverse -p. // - Notice that this is a different overload from the binary // operator- above. The compiler can distinguish them because // unary - has one argument while binary - has two. Rational operator-( Rational const &p ); /////////////////////////////// // Other rational operations // /////////////////////////////// // Return the absolute value of p. // // C++ already has an abs(...) function for numerical types, // so using the same identifier is natural for Rational. Rational abs( Rational const &p ); // Calculate the multiplicative inverse of p. // // There is no existing C++ operator that naturally represents // taking a multiplicative inverse, so this remains an ordinary // function. Rational inverse( Rational const &p ); ////////////////////////// // Comparison operators // ////////////////////////// // Determine whether p and q are equal using p == q // instead of equal( p, q ). bool operator==( Rational const &p, Rational const &q ); bool operator==( Rational const &p, int const n ); bool operator==( int const n, Rational const &p ); // Determine whether p and q are different using p != q // instead of unequal( p, q ). bool operator!=( Rational const &p, Rational const &q ); bool operator!=( Rational const &p, int const n ); bool operator!=( int const n, Rational const &p ); // Determine whether p < q. bool operator<( Rational const &p, Rational const &q ); bool operator<( Rational const &p, int const n ); bool operator<( int const n, Rational const &p ); // Determine whether p <= q. bool operator<=( Rational const &p, Rational const &q ); bool operator<=( Rational const &p, int const n ); bool operator<=( int const n, Rational const &p ); // Determine whether p >= q. bool operator>=( Rational const &p, Rational const &q ); bool operator>=( Rational const &p, int const n ); bool operator>=( int const n, Rational const &p ); // Determine whether p > q. bool operator>( Rational const &p, Rational const &q ); bool operator>( Rational const &p, int const n ); bool operator>( int const n, Rational const &p ); /////////////////////////// // Output and conversion // /////////////////////////// // Approximate p by a double-precision floating-point value. double real( Rational const &p ); // Return a string representation of p. // // This is not an overloaded operator and is unchanged in // principle from the previous project. std::string to_string( Rational const &p ); // Insert a string representation of p into the output stream. // // Overloading operator<< allows us to write // // std::cout << p; // // The first argument is the output stream and the second // argument is the Rational object to be inserted. // // The output stream is returned by reference so that // insertions can be chained: // // std::cout << p << q << std::endl; std::ostream &operator<<( std::ostream &out, Rational const &p ); ////////////////////// // Class definition // ////////////////////// // Store the numerator and denominator of a rational number. // // This class is unchanged from the previous Rational // project. The important change in this project is how // functions operating on Rational objects are named and // consequently how they can be called. class Rational { public: int numer_; int denom_; };