The Rational Class .cpp

The .cpp file typically holds the source code, the bodies, of the functions defined in the header file. Here are the functions for the sample Rational class. Note that the sample code is not well-documented, although there are function separater comment lines to make following the code easier.

The .cpp file   --   the whole thing: rat.cpp

The #include at the start of the file

#include "rat.h"

is needed so all the identifiers and function prototypes are known when you write the code for the functions. Recall that every identifer must be known to the compiler (defined) before you use it. Recall that the filename is in double quotes instead of pointed brackets because it's written by the programmer.

First consider the constructor:
Rational::Rational(int n, int d) { 
   numerator = d < 0 ? -n : n; 
   denominator = d < 0 ? -d : d; 
   reduce(); 
}

The first Rational refers to the class. The binary scope operator, the ::, ties the constructor/function name, Rational, to the class.

Since the functions are defined in different files, and many different classes could own the same named function as a part of them, e.g., display(), this mechanism is used to tie the function name to the class it is from.

As for the body of the code, the parameters are used to set the data members, numerator and denominator. The question-mark operator is used to make sure if the fraction is negative, the negative is always stored in the numerator. After the numerator and denominator are computed, the fraction is reduced to lowest terms using the reduce function.

Now consider the add function:
Rational Rational::add(const Rational& a) {
   Rational t;

   t.numerator = a.numerator * denominator + a.denominator * numerator;
   t.denominator = a.denominator * denominator;
   t.reduce();

   return t;
}

As with the constructor, the add function is tied to the Rational class with the binary scope operator. The first Rational is the return type of the function.

The parameter is a Rational object to be added to the current object. Recall that it is "fake" pass-by-value. The ampersand says to pass-by-reference but the const says to cast it to a constant while it's in this function. A local object, t, is used for the computation. After the numerator and denominator for t are computed, it's reduced to lowest terms and returned.

When the identifier "numerator" or "denominator" is used by itself, it's always the numerator or denominator of the current object, as opposed to t.numerator which refers to the numerator of t. You can also use this but in C++, it's a pointer, not a reference, so you can't use it with the dot operator. This is discussed in more detail in the Array example.

The subtract, multiply, and divide functions are all similar to add.
void Rational::printRational() {
   IF (denominator == 0)
      cout << endl << "DIVIDE BY ZERO ERROR!!!" << endl;
   else if (numerator == 0)
      cout << 0;
   else
      cout << numerator << "/" << denominator;
}
There is nothing too exciting about printRational() and printRationalAsFloat(). They are void with nothing returned and they both check for dividing by zero.

The last function in the file is reduce(). It is a utility function and the only private function in the class (although you can't tell it's private from the .cpp file). It is also void, simply replacing numerator and denominator with their lowest term values. The algorithm for reducing finds the greatest common denominator of the numerator and denominator and then divides them by it.