The Rational Class header file

Here is a very simple, sample C++ class. Note that this code is not well-documented. We'll see good documentation later. The class defines a Rational object, a fraction with a numerator and denominator. We'll go through the code a little at a time.

The header file   --   the whole thing: rat.h

The header file typically contains the definition of the class which includes the data members and member function prototypes (just the function header). This is the Rational object blueprint, it defines what an object will look like, i.e., what data the object manipulates and the object's interface, the operations it can perform.

The #ifndef, #define, and #include
First consider the preprocessor statements at the beginning of the .h file:

#ifndef RAT_H
#define RAT_H

These are strictly for the compiler. This says if the identifier RAT_H (my made up identifier similar to the filename so it's easy to not repeat an identifier) is not already defined (the ifndef), then define it (the define). The   #ifndef   must have a matching   #endif   at the end of the .h file.

Every identifier in your entire program is put into the compiler's symbol table, which is nothing more than a huge data structure holding every identifier in the entire program. Along with the identifier name, everything about it is stored there, e.g., type if it's a variable, parameter types if it's a function, number of dimensions if it's an array, and so on. This is so the compiler can give you nice errors when you do something like try to define a varible more than once. The first time you define it, it goes in the symbol table. The second time you try to define, it finds it in the table already and gives you an error.

#include < iostream >

The #include includes other routines. This is similar to the import in Java. When it's in a C++ library, you use the pointed brackets. When you include something you wrote yourself, it goes in double quotes. The library iostream includes all the routines used for standard input and output.

The using namespace
using namespace std;

Typically in real life, you wouldn't use a using statement. This says that you are using the names in the std (the standard library). We do this to save typing since we are going to use standard input and output primarily for testing purposes, to display output so we can check it's correct. If we didn't do this, then we'd have to qualify every cin and cout we used. For example, instead of just typing "cout" for printing, we'd have to type "std::cout" .

The class and public
Now we'll go line by line through the class definition.

class Rational {

This defines the class. All classes are public. By defining a class, we are defining a brand new type of thing. The keyword public says whatever follows it are public. It can go anywhere in the class definition and can appear more than once, although typically programmers put all the public members together and all the private members together.

Default values for parameters
  Rational(int = 0, int = 1);

This is the constructor with two int parameters. The values on the parameters are default values. If values are not passed in, then a 0 and/or 1 are used for the two parameter values. That means that this one constructor is equivalent to the following three constuctors:
Rational(int, int);      
If no values are passed in, then a 0 and 1 are used for the two parameter values. If one number is passed in, then it is used for the first int parameter and a 1 is used for the second parameter. If two numbers are passed in, then those values are used for the parameters.

You can use default value parameters in any function. A function can have both parameters that don't have default values and ones that have them. But if you use both, all parameters that have default values must be at the right end of the parameter list, for example,
void someFunction(int, double, int, int=0, int=0);

  Rational add(const Rational &);
  Rational subtract(const Rational &);
  Rational multiply(const Rational &);
  Rational divide(const Rational &);
  void printRational();
  void printRationalAsFloat();

Nothing very different here. The first four routines return a Rational object. The first four routines all have one parameter, one Rational object that will be used, but not changed. This is "fake" pass-by-value, really pass-by-reference, but the const in front says cast it to a constant in this routine.

The private members
  int numerator;
  int denominator;
  void reduce();

The keyword private says to make the three members private. As always, the data, numerator and denominator, are private. The reduce function is also private since it's a utility function (reduces all rationals to lowest terms, e.g., 2/4 is stored as 1/2). My use of the phrase "utility function" means that it is used by other functions, but isn't part of the user interface, meaning the user will never use it directly.

End of the .h file
And don't forget that semicolon after the closing curly bracket at the end of the class definition. It makes no sense at all in C++ now, comes from legacy C code. Programmers didn't used to write the definition separately from the variable declaration (or object instantiation) like they do now.


This #endif goes with the #ifndef that started the file. This is similar to how { } are used in code.