#include #include "Rational.hpp" // Compile this file together with Rational.cpp. // // This file contains a main() function. A C++ program can // have only one main() function. If your project already // contains a main.cpp file, either: // // 1. remove main.cpp from the project or build, or // // 2. temporarily rename its main() function to old_main(). // // The second option allows the original demonstration // program to remain in the project while this program is // being compiled and run. int main() { // The member variables of Rational are public. This // allows the user to create an invalid rational number. Rational p{}; // The default values are both zero, so p represents 0/0. std::cout << "After Rational p{}:" << std::endl; std::cout << "p.numer_ = " << p.numer_ << std::endl; std::cout << "p.denom_ = " << p.denom_ << std::endl; // A denominator of zero does not represent a rational // number. // // The user can also explicitly create such an object. Rational q{ 3, 0 }; std::cout << std::endl << "After Rational q{ 3, 0 }:" << std::endl; std::cout << "q.numer_ = " << q.numer_ << std::endl; std::cout << "q.denom_ = " << q.denom_ << std::endl; // Even if a Rational object is initially valid, the user // can subsequently make it invalid. Rational r{ 3, 4 }; std::cout << std::endl << "Initially, r = " << r << std::endl; r.denom_ = 0; std::cout << "After r.denom_ = 0:" << std::endl; std::cout << "r.numer_ = " << r.numer_ << std::endl; std::cout << "r.denom_ = " << r.denom_ << std::endl; // There is another issue. We would like every rational // number to be stored in a normal form: // // 1. The denominator is positive. // 2. The numerator and denominator have no common // divisor greater than one. // // For example, all four of these objects represent the // same rational number. Rational s1{ -1, 2 }; Rational s2{ 100, -200 }; Rational s3{ -47, 94 }; Rational s4{ 99, -198 }; std::cout << std::endl << "Equivalent representations:" << std::endl; std::cout << "s1 = " << s1 << std::endl; std::cout << "s2 = " << s2 << std::endl; std::cout << "s3 = " << s3 << std::endl; std::cout << "s4 = " << s4 << std::endl; // We could write a function that normalizes a Rational // object. However, as long as the member variables remain // public, the user can immediately undo that work. Rational t{ -1, 2 }; std::cout << std::endl << "Initially, t = " << t << std::endl; // The user can replace its representation with a // non-normal representation. t.numer_ = 100; t.denom_ = -200; std::cout << "After directly modifying its members:" << std::endl; std::cout << "t = " << t << std::endl; // Thus, functions operating on Rational objects cannot // safely assume that: // // denom_ != 0 // // or that the Rational object is in normal form. // // As long as these member variables are public, every // operation must be prepared for the possibility that // the user has changed them. return 0; }