Most of the problems we have examined have had relatively simple
 solutions, because the data objects in the problem could be
 represented using the predefined C++ types.  We can represent a menu
 with a string, a choice from that menu with a char,
 the radius of a circle with a double, and so on.
 
The problem is that real-world problems often involve data objects that cannot be directly represented using just a single, predefined C++ type.
Let's consider two different problems.
Problem #1: Cartesian points. In the algebra courses you've taken, you have probably graphed some functions on a two-dimensional graph. These graphs typically use a Cartesian coordinate system, with x- and y-coordinates, to plot the points.

This graph plots the point (7,3), which is 7 units to the right along the x-axis and 3 units up along the y-axis. In this lab, we'll only worry about representing a single point. This work, though, could easily be used in a program to generate some actual graphs in a Cartesian coordinate system.
Problem #2: Fractions. The other problem is doing fractional arithmetic. Suppose that we know a certain gourmet chef named Pièrre whose recipes are written to make 12 servings. There a few difficulties:
We will work through two programs to manipulate fractions.
Coding.  Keep in mind that you will write the code
 for the Fraction class.  The Coordinate class is
 presented here as an example to help you write code for the Fraction class.
 
Directory: lab11
 
Fraction.h, Fraction.cpp, and
   Fraction.doc implement the Fraction class.gcd.h and gcd.cpp implement
   Euclid's greatest-common-divisor algorithm (used by the Fraction class).pierre1.cpp and pierre2.cpp are
   drivers for the Fraction class.Makefile is a makefile.gcc users need a makefile; all others
   should create a project and add all of the .cpp files to
   it.
   Add your name, date, and purpose to the opening documentation of the code and documentation files; if you're modifying and adding to the code written by someone else, add your data as part of the file's modification history.
Take a moment to compare the programs in pierre1.cpp and
 pierre2.cpp.  Both programs implement the same basic algorithm:
 
oldMeasure, the fractional measure to be converted.scaleFactor, the fractional conversion factor.newMeasure = oldMeasure * scaleFactor.newMeasure.A solution to Pièrre's problem is quite simple, if we have the ability to define, input, multiply and output fraction objects. That's the work we'll be doing in this lab.
The two programs differ only in how they read and write fraction objects. The second version has a more familiar look to it, but will require more work from us. So the first version will be useful for getting something workable, but it's missing some input and output features.
The difficulty is that there is no predefined C++ type Fraction.  In such very common situations, C++ provides a
 mechanism by which a programmer can create a new type and its
 operations.  This mechanism is called a class.
 
In C++, a new type can be created by
The class structure mentioned in this second step looks like this:
class TypeName
{
  public:
  private:
};
 where TypeName is a name describing the new type.  A class
 is (almost) always defined in a header file.
 A class has two sections, a public section and a private section. The public section is where class operations are declared, and the private section is where class attributes are declared.
Let's first consider a point in Cartesian coordinates. A point consists of an x-coordinate and a y-coordinate. We can easily write two variables to hold these two values:
double myX, myY;
Of course, the context for this declaration is all important. We declare these variables in an appropriately-named class structure, making them instance variables:
class Coordinate
{
  public:
  private:
    double myX, myY;
};
 We use the prefix "my" at the beginning of a name for an
 instance variable name to encourage an internal
 perspective.  We imagine ourselves as the object we're trying to
 describe.  For example, when figuring out these instance variables, I
 could say, "I am a Cartesian coordinate, and I have an x-coordinate
 and a y-coordinate."  Since they are my attributes, I label
 them as such.  This way I shouldn't get them confused with other
 objects that I work with.
 
The result is a new type, named Coordinate, which can be used
 as a type for new objects:
Coordinate point1, point2, point3, point4;
Each point has two Idouble components,
 one named myX and the other named myY.  This is why
 myX and myY are known as instance variables: every
 instance of a Coordinate has its own copies of these
 variables.  The neat thing is that we only had to declare myX
 and myY once in the class definition.
 
We can now expand our general pattern for a class definition:
classwhere eachTypeName{ public: private:Type1InstVarList1;Type2InstVarList2; ...TypeNInstVarListN; };
TypeI is any defined type and each
 InstVarListI is a list of instance variables of
 type TypeI.
 Now let's apply this same thinking to the fraction problem.  We first
 need to identify the attributes of a Fraction object.  Here
 are a few fractions:
1/2 4/3 4/16 16/4Each fraction has the form:
wherenumber1/number2
number1 is called the numerator
 and number2 is called the denominator.
 A fraction needs both a numerator and a denominator.  However, the
 / symbol is common to all fractions, and so it is not
 recorded as an attribute of a fraction.  Consequently, a fraction has
 just two attributes, a numerator and a denominator, both of which are
 integers.
 Edit the file Fraction.h:
 
Fraction.myNumerator and myDenominator.Given this declaration of Fraction, we can make the following
 declarations:
Fraction oldMeasure; ... Fraction scaleFactor;These declarations define two objects with the following forms:

Again, note that each instance of type Fraction has its own
 copy of each of the attributes we defined; that's why they're called
 instance variables.  It's also why we prefix the variable name
 with "my", to encourage an internal perspective.
 
In the source program pierre1.cpp, uncomment the definition
 of oldMeasure.  (Do not uncomment anything else, yet.)
 Compile your source program to test the syntax of what you have
 written.  When it is correct, continue to the next part of the
 exercise.
 
Besides having instance variables, a class can also have methods. A method is a function declared inside a class to provide an operation for objects of the class.
We've used several methods already.  A vector has a size() method.  A string has a substr() method.  But
 until now we've only used methods.  Now we get to define our
 own methods in our own classes.
 
Methods are prototyped within the class structure itself (in the
 header file), and they are normally defined in the class
 implementation file.  However, very simple methods (i.e., ones that
 fit on a single line) are defined "inline": in the header file, following the
 class declaration, prefixed by the keyword inline.  The
 reasons for this are a bit technical and beyond the scope of what
 we're really trying to do.  Just remember to define simple methods in
 the header file with an inline in front of them.
 
One of the characteristics of a class is that its instance variables
 are kept private, meaning that a
 program using the class is not permitted to directly access them.
 Mostly this is an issue of trust.  In the case of a Coordinate object, it probably wouldn't be too bad if other
 programmers had direct access to the myX and myY
 instance variables.  However, in the Fraction class, we must
 make sure that myDenominator does not become zero since
 division by 0 is undefined.  If we hide away myDenominator
 from the casual programmer, we can write the methods of the Fraction class so that myDenominator never becomes 0.
 
In practice, it is not worth the time and effort to try to figure out which instance variables are safe to let everyone access directly. Common practice is to make all instance variables private.
On the other hand, we do want users of the class to be able to
 access the operations of a class.  As a result, the operations should
 be declared in the public section
 of the class.  Anything defined in the public section can be accessed
 through an instance of the class from any part of the program.  So,
 wherever we have a Fraction object, we will be able to access
 its public operations.
 
By convention, the public section of a class comes first, so that a
 user of the class can quickly see what operations it provides.  It is
 good style to have one public section and one private section in a
 class; however, C++ allows the keywords public: and private: to appear an arbitrary number of times in a class
 declaration.
 
We have seen that methods are called differently from normal
 functions: if two string objects named greeting and
 closing are defined as follows:
string greeting = "hello",
       closing = "goodbye";
 then the expression
cout << greeting.size() << ' ' << closing.size() << endl;prints
5 7, the sizes of the two strings.
 Object-oriented programmers like to think of a call to a method as a
 message to which the object
 responds.  When we send the size() message to greeting, greeting responds with the number of characters it
 contains; and if we send the same size() message to closing, closing responds with the number of characters it
 contains.  This is part of the internal perspective for designing and
 writing a class.  When we use the string class, we're not
 responsible for its operations.  We just simple ask the string objects to carry out various actions.
 
As you might expect, defining a method is also a bit different from defining a normal function.
pierre1.cppIn this first part of this exercise, we will focus on adding the
 methods to class Fraction needed to get pierre1.cpp
 operational.
 
To facilitate debugging a class, it is often a good idea to begin with a method that can be used to display class objects---an output method.
From the perspective of our Coordinate class, we can specify
 the task of such a method, which we'll call print(), as
 follows:
 
Specification:Note the use of internal perspective (e.g., "...I write my value.").receive:out, anostreamto which I write my values.
output:myXandmyY, as an ordered pair.
passback:out, containing the output values.
Also note that this method receives and passes back an ostream.  The rule is very simple:
 
Rule: All streams are passed by reference---received and passed back. 
The reasons for this are fairly technical and are beyond what we really need to know right now, but this is hard-and-fast rule.
Methods must be prototyped within the class declaration, so we would write:
class Coordinate
{
  public:
    void print(ostream & out) const;
  private:
    double myX, myY;
};
 Whoa!  Where did that const come from?  Internal perspective
 is an easy perspective for explaining this: "I am a Coordinate object, and when I am printed using print(), I
 should not change."  It's the const that adds the "I should
 not change".  Think about it: a Coordinate object that
 changes every time we print it would be quite useless.  We can get
 the compiler to enforce this observation by adding const
 after the parameter list for the method; now, the compiler will not
 let us change myX or myY in the method definition.
 
Also, we've put print() in the public section of the class.
 This is quite typical.  It's very common for programmers to print out
 coordinates in their programs, so it's an operation that we want to
 make available to everyone.  Hence, it goes in the public section.
 
Whenever you declare a method, take a bit of time to think if the
 method should change the instance variables of the class.  If you
 even suspect they shouldn't change, add the const.  You
 can always take it away later if you discover you do need to
 change the contents of an instance variable.  (We'll see a method
 that does very soon.)
 
This is a fairly simple method, so we would define it within the
 header file Coordinate.h, following the declaration of class
 Coordinate.  As an inline method, we would precede its
 definition with the keyword inline.
 
To define print(), we must inform the compiler that this is a
 method of a class.  This is done by preceding the name of the method
 with the name of the class of which the method is a member and the
 scope operator
 (::).  That is, we would define print() as a method of our
 Coordinate class as follows:
inline void Coordinate::print(ostream & out) const
{
  out << '(' << myX << ',' << myY << ')';
}
 inline indicates that this is a simple method that should
   be inlined.void tells the compiler that this method returns nothing.Coordinate:: tells the compiler that this method is a
   member of class Coordinate.print is the name of the method.(ostream & out) is the parameter list of the method.const tells the compiler that this method should not
   modify any of the instance variables of class Coordinate.Note that const must be present in both the prototype
 and the definition of a method that does not modify its
 instance variables.  In contrast, inline is used only
 with the definition, not the prototype.
 
Let's consider what happens when this method is invoked.  As with
 anything class related, this makes the most sense in an internal
 perspective: "I am a Coordinate object, and when someone
 sends me a message telling me to print myself out, I send a left
 parenthesis, my x-coordinate, a comma, my y-coordinate, and a right
 parenthesis to the provided ostream."  Note how the "my" prefix makes the code similar to this statement; also note the
 message metaphor.
 
Let's see if you have the hang of this:
Question #11.1: Ifpointis aCoordinateobject whose x-coordinate is 3 and whose y-coordinate is 4, then what does the statementpoint.print(cout);display?
Question #11.2: Iforiginis aCoordinateobject whose x-coordinate is 0 and whose y-coordinate is 0, then what does the statementorigin.print(cerr);display?
As seen in the method definition above, a method can directly access
 the private instance variables of the object.  Otherwise, the private
 instance variables would remain hidden to all code everywhere, making
 them quite useless.  Someone should be able to access them, and why
 not myself?  If I'm a Coordinate object and someone asks me
 to print myself, I should be allowed to access my private
 instance variables.
 
Using all of this, prototype and define a similar print()
 method for your Fraction class.  Write the method so that
 when oldMeasure is a Fraction whose numerator is 3
 and whose denominator is 4, then a message:
oldMeasure.print(cout);will display
3/4
Prototype this method in the public section of class Fraction, and define it as an inline method following the
 declaration of class Fraction in Fraction.h.  Check
 the syntax of your method, and continue when it is correct.
 
An output operation for a class is of little use unless we are able to define and initialize objects of that class. The action of defining and initializing an object is called constructing that object. To allow the designer of a class to control the construction of class objects, C++ allows us to define a special function of a class called a constructor. A constructor specifies what actions are to be taken when a class object is constructed. When an instance is declared, the compiler calls this constructor function to initialize the object's instance variables.
For example, what should happen when we declare a new Coordinate object like so:
Coordinate point;Presently, there would be junk in this object's instance variables. It seems reasonable, though, to initialize the x- and y-coordinates to 0.
We might specify this as a postcondition (as part of a specification):
Specification:postcondition:myX== 0.0 andmyY== 0.0.
A constructor does not return anything to its caller; it initializes the instance variables of an object when that object is defined. We specify this behavior as a boolean expression which is true when the constructor terminates. Such an expression is called a postcondition, since it is a condition that holds true after (i.e., "post") the constructor finishes.
A postcondition is not code you should write.  It's a test that
 should be true if you tested it at the end of the constructor.
 You can test a postcondition if you want (using an assert()), and this may be a good idea (especially if there's a lot
 of code and there's a bug you can't find).  But it's not necessary.
 Instead, a postcondition indicates what other code you should
 write.  In this case, what code can I execute so that myX
 is 0.0?  The answer is below.
 
In order for a constructor to be a member of a class, its prototype must appear within the class. Unlike other functions, C++ determines the name of this function:
Rule: The name of a constructor is always the name of the class. 
So we prototype this constructor in the public section of class
 Coordinate, as follows:
class Coordinate
{
  public:
    Coordinate();
    void print(ostream & out) const;
  private:
    double myX, myY;
};
 Unlike our print() method, a constructor initializes (i.e.,
 modifies) the instance variables of a class.  As a result, it should
 not (and cannot) be prototyped or defined as const.  So
 the "missing" const is understandable.
 
However, where's the return type?!! Every function has had a return type. C++ insists on it. Well, in fact, C++ will equally insist that a constructor does not have a return type. As observed above, a constructor never returns anything to its caller; it initializes its instance variables. The object itself has already been created, so that doesn't have to be returned. It just needs to be initialized. So constructors do not need a return type.
As with the print() method, we want everyone to be able to
 construct Coordinate objects, so the prototype should be
 placed in the public section of the class.
 
Also, as before, simple definitions should be placed in the class
 header file, designated as inline functions.  To define an inline
 Coordinate constructor, we thus write this funny-looking
 definition in the header file:
inline Coordinate::Coordinate()
{
  myX = 0.0;
  myY = 0.0;
}
 The first Coordinate is the name of the class, telling the
 compiler that this is some member of class Coordinate.  The
 second Coordinate is the name of the constructor.
 Given this definition, when a Coordinate object is defined,
 the compiler will call this constructor to initialize the new object,
 setting the object's myX and myY instance variables
 to zero.
 
The pattern for a constructor is thus:
where the firstClassName::ClassName(ParameterList) {StatementList}
ClassName refers to the name of the class,
 the second ClassName names the constructor, and StatementList is a sequence of statements that initialize the
 instance variables of the class.
 Constructors can take parameters, which are defined as they would be for any other function, and any valid C++ statement can appear in the body of such a constructor.
Using this information, prototype and define a constructor for your
 Fraction class, that satisfies the following specification:
Specification:That is, the definition:postcondition:myNumerator== 0 andmyDenominator== 1.
Fraction oldMeasure;should initialize the instance variables of
oldMeasure
 appropriately to represent the fraction 0/1.  (Remember that division
 by 0 is a Bad Thing, so initializing it to 0/0 is not advisable.)
 Store the prototype in the public section of class Fraction,
 and define it as inline, following the declaration of class
 Fraction, in Fraction.h.  Test the syntax of what you
 have written, and continue when it is correct.
 
A class can have multiple constructors, so long as each definition is distinct in either the number or the type of its parameters. Defining the same function multiple times is called overloading the function. Overloading works for normal functions, methods, and constructors.
Suppose that we would like to be able to explicitly initialize the x-
 and y-coordinates of a Coordinate object to two values
 specified by the programmer creating the object.
 We can specify this as follows:
 
Specification:receive:xandy, twodoublevalues.
postcondition:myX==xandmyY==y.
We can overload the Coordinate constructor with a second
 definition, one that takes two double arguments and uses them
 to initialize our instance variables:
inline Coordinate::Coordinate(double x, double y)
{
  myX = x;
  myY = y;
}
 Note the benefit of using the "my" prefix: we don't have to
 come up with silly or awkward names for the parameters here.  If we
 called the instance variables x and y, we'd have to
 come up with different names for these parameters.  This convention
 also clarifies the internal perspective: myX is my
 x-coordinate while x is an x-coordinate that something else
 has handed to me.
 
As usual for such a simple function, this constructor is defined
 inline in the header file, and like all methods of a class, its
 prototype would be placed in the public section of class Coordinate:
class Coordinate
{
  public:
    Coordinate();
    Coordinate(double x, double y);
    void print(ostream & out) const;
  private:
    double myX, myY;
};
 We can declare Coordinate objects to
 invoke this constructor:
Coordinate point1,
           point2(1.2, 3.4);
 Our first constructor initializes point1 since its
 declaration has no arguments and the first constructor has no
 parameters.  Our second constructor initializes point2 since
 its declaration has two double arguments and the second
 constructor has two double parameters.  After these
 declarations, we have these objects:
 
Using this information, define and prototype a second Fraction constructor that satisfies this specification:
 
Specification:Consequently, the definitionsreceive:numeratoranddenominator, two integers.
precondition:denominatoris not 0.
postcondition:myNumerator==numeratorandmyDenominator==denominator.
Fraction oldMeasure; ... Fraction scaleFactor(1, 6);should initialize
oldMeasure to 0/1, and initialize scaleFactor to 1/6.
 Use a call to assert() to ensure the precondition.
 
Use the compiler to test the syntax of what you have written.  When
 the syntax is correct, use pierre1.cpp to test what you have
 done, by inserting calls to print() to display their values:
... oldMeasure.print(cout); ... scaleFactor.print(cout);
Also try initializing scaleFactor with a zero denominator.
 Make sure that the assert() is triggered.
 
When your constructors and methods are working correctly, remove this
 test code from pierre1.cpp.
 
It might be useful to be able to extract the x- and y-coordinates of
 a Coordinate object.  It is common to need the values stored
 in an object, and the methods that return these values are generally
 known as accessor
 methods.
 
As with most classes, the accessor methods for the Coordinate
 class have very simple specifications:
 
Specification:andreturn: my x-coordinate.
Specification:return: my y-coordinate.
Since these methods do not modify any of the instance variables, we
 can declare them as const methods.  Generally, accessor
 methods begin with the prefix "get" followed by the name of
 the attribute (without "my").  So, two new prototypes
 are added:
class Coordinate
{
  public:
    Coordinate();
    Coordinate(double x, double y);
    double getX() const;
    double getY() const;
    void print(ostream & out) const;
  private:
    double myX, myY;
};
 We would then define these simple methods in the header file as follows:
inline double Coordinate::getX() const
{
  return myX;
}
inline double Coordinate::getY() const
{
  return myY;
}
 Suppose we declare two Coordinate objects point1 and
 point2:
 

Question #11.3: What do these expression evaluate to:point1.getX()andpoint2.getY()?
This is another reason for the "my" prefix.  We can use the
 my-free names as the name of a method that accesses the value
 of that instance variable.
 
Using this information, add to class Fraction an accessor
 method getNumerator() that satisfies this specification:
 
Specification:Also write an accessor methodreturn:myNumerator.
getDenominator() that satisfies
 this specification:
 Specification:Since these are simple methods, define themreturn:myDenominator.
inline following
 the class declaration in the header file.  Test their syntax by
 compiling the code and continue when they are correct.
 Once we are able to define Fraction objects, it is useful to
 be able to input a Fraction value.  To illustrate, suppose
 that we wanted to input a Coordinate value that looked like
 this:
(3,4)A user would type this in, or perhaps a program would read this in from a file.
We can specify the problem as follows:
Specification:receive:in, anistream.
precondition:incontains aCoordinateof the form(x,y).
input:(x,y), fromin.
passback:in, with the input values extracted from it.
postcondition:myX==x&&myY==y.
We prototype this method in the class (as with all methods), although
 this one is not const because it modifies the instance
 variables:
class Coordinate
{
  public:
    Coordinate();
    Coordinate(double x, double y);
    double getX() const;
    double getY() const;
    void read(istream & in);
    void print(ostream & out) const;
  private:
    double myX, myY;
};
 We can define read() as a method that satisfies the
 specification, as follows:
void Coordinate::read(istream & in)
{
  char ch;         // for reading ( , and )
  in >> ch         // read '('
     >> myX        // read x-coordinate
     >> ch         // read ','
     >> myY        // read y-coordinate
     >> ch;        // read ')'
}
 Testing pre- and postconditions for an input method is tricky at best, so don't worry that we haven't tested them here. They're good to write down anyway so that we're clear on what we expect.
The input specification indicates that a coordinate in the input will
 have punctuation around it: parentheses and a comma.  The ch
 variable is used to read in these characters and throw them away.
 It's useful to have them in the input to make the input more
 readable, but they're frivolous in a Coordinate object since
 every Coordinate object is written with this
 punctuation.  We only need it in the input and output.
 
Given the length of this method, it's pressing the boundaries of what
 some compilers define as "simple"; some won't allow us to declare it
 inline.  As a result, we define it in the implementation file
 (without the keyword inline).
 
With this method, the statements
Coordinate point; point.read(cin);reads a
Coordinate of the form (x,y) from cin.
 Using this information, define and prototype an input method named
 read() for class Fraction.  Your method should
 satisfy this specification:
 
Specification:receive:in, anistream.
precondition:incontains a Fraction value of the formn/danddis not zero.
input:n/d, fromin.
passback:in, withFractionn/dextracted from it.
postcondition:myNumerator==nandmyDenominator==d.
Some differences from the read() of Coordinate:
 
d is not zero).  Use a call to assert().After you've written and successfully compiled this new method, you should be able to uncomment the statements:
oldMeasure.read(cin); ... scaleFactor.read(cin);
Test your input method by adding print() statements after the
 read() statements in pierre1.cpp to test the input
 routines.  Compile and run the program, and continue when read() works correctly.  Remove the test print()
 statements.
 
We have seen that methods like constructors can be overloaded.  In
 addition, C++ allows us to overload operators, such as the arithmetic
 operators (+, -, *, /, and %).  However to do so, we need to rethink the way expressions work.
 
Suppose that we want to permit two Coordinate objects to be
 added together.  In C++'s object-oriented world, an expression like
point1 + point2is thought of as sending the
+ message to point1,
 with point2 as a message argument.  We can specify the
 problem from the perspective of the Coordinate receiving this
 message:
 Specification:receive:point2, a Coordinate.
return:result, a Coordinate.
postcondition:result.myX==myX+point2.myXandresult.myY==myY+point2.myY.
Again, the postcondition here suggests the code that we should write, and it doesn't particularly warrant testing at the end of the method.
According to our specification, this operation does not modify the
 instance variables of the Coordinate that receives it, and so
 we write the following prototype:
class Coordinate
{
  public:
    Coordinate();
    Coordinate(double x, double y);
    double getX() const;
    double getY() const;
    void read(istream & in);
    void print(ostream & out) const;
    Coordinate operator+(const Coordinate & point2) const;
  private:
    double myX, myY;
};
 Not only is the method itself const, but the parameter is
 const as well.  We don't change either object.  We pass the
 parameter by reference because it's not a primitive type; recall that
 passing by reference is a bit faster than by value for non-primitive
 types.
 
One way to define this method is as follows:
Coordinate Coordinate::operator+(const Coordinate & point2) const
{
  Coordinate result(myX + point2.getX(), myY + point2.getY());
  return result;
}
 This definition uses our second constructor to construct and
 initialize result with the appropriate values.
 This function illustrates that, for any overloadable operator
 Δ, we can use the notation operatorΔ as the name
 of a function that overloads Δ with a new definition.
 
Once such a method has been prototyped and defined as a member of
 class Coordinate, we can write familiar looking expressions,
 such as
point1 + point2to compute the sum of two
Coordinate objects point1
 and point2.
 The C++ compiler treats such an expression as an alternative notation for the method call:
point1.operator+(point2)
While it is useful to overload all of the arithmetic operators for a
 Fraction, the particular operation that we need in order to
 solve our problem is multiplication (the others, we leave for the
 exercises).  From the preceding discussion, it should be evident that
 we need to overload operator* so that the expression in
 pierre1.cpp:
oldMeasure * scaleFactorcan be used to multiply the two
Fraction objects oldMeasure and scaleFactor.
 However, the math here is a bit more involved that in the past examples and tasks. We can get some insight into the problem by working some simple examples:
The specification for such an operation can be written as follows:
Specification:receive:rightOperand, aFractionoperand.
return:result, aFraction, containing the product of the receiver of this message andrightOperand, simplified, if necessary.
We can construct result by taking the product of the
 corresponding instance variables and then simplifying the resulting
 Fraction.
 
For the moment, ignore the problem of simplifying a Fraction.
 Extend your Fraction class with a definition of operator* that can be used to multiply two Fraction objects.
 When we add the code to simplify result, this method will
 be reasonably complicated, so define it in the implementation file
 (and, of course, prototype it in the header file, in the class
 definition).  Test the correctness of what you have written by
 uncommenting the lines in pierre1.cpp that that compute and
 output newMeasure.  Continue when your multiplication
 operation yields correct (if unsimplified) results.
 
The main deficiency of our implementation of operator* is its
 inability to simplify improper fractions.  That is, our
 multiplication operation would be improved if class Fraction
 had a simplify() operation, such that fractions like:
 2/6, 6/12, 12/4 could be simplified to 1/3, 1/2, and 3/1, respectively.
 
Such an operation is useful to keep fractional results as simple and
 easy to read as possible.  To provide this capability, we will
 implement a Fraction method named simplify().  In a
 method like operator* which constructs its answer in a Fraction named result, simplify() can be invoked
 like so:
result.simplify();to simplify the
Fraction in result.
 It will help to phrase this in message passing terms.  This calls
 says, "Hey, result!  Simplify yourself!"  result then
 goes off and simplifies itself (e.g., changes itself from 12/4 to
 3/1).  I don't expect anything back; I've told result to do
 all the work and change itself.
 
That takes care of result in the multiplication operation,
 but what about the definition of simplify()?  We shift our
 perspective to the Fraction that's been told to simplify
 itself.  There are a number of ways to simplify a fraction.  One way
 is the following algorithm: 
gcd, the greatest common divisor of myNumerator and myDenominator.myNumerator by myNumerator/gcd.myDenominator by myDenominator/gcd.Those "replace" steps are assignment statements: e.g., "Change my numerator to be my numerator (my old one) divided by the GCD." Read this statement carefully, and the code writes itself.
The specification for this method is thus:
Specification:postcondition:myNumeratorandmyDenominatordo not share an common factors (i.e., the fraction is simplified).
Remember that simplify() doesn't need any extra information,
 except the Fraction object that it's invoked on, so there are
 no parameters.  Also, the object that receives this message changes
 itself, so it cannot be declared const.  And there's no
 need to return anything.  So we end up with only a postcondition in
 our specification.
 
The implementation file gcd.cpp contains a function greatestCommonDivisor() that implements Euclid's algorithm for
 finding the greatest common divisor of two integers.  Using greatestCommonDivisor() and the preceding algorithm, define simplify() as a method of class Fraction.
 
Since this is a complicated operation, define it in the implementation file, and only prototype it in the header file.
We have now provided all of the operations needed by pierre1.cpp, so the complete program should be operable and can be
 used to test the operations of our Fraction class.
 
pierre2.cppIn this second part of this exercise, we add the functionality to
 class Fraction in order for pierre2.cpp to work
 properly, so use your text editor to open it for editing.
 
While we have provided the capability to output a Fraction
 value via a print() method, doing so requires that we write
 clumsy code like:
cout << "\nThe converted measurement is: "; newMeasure.print(cout); cout << "\n\n";instead of elegant code like:
cout << "\nThe converted measurement is: " << newMeasure << "\n\n";
Our print() method does solve the problem, but its solution
 doesn't fit in particularly well with the rest of the iostream library operations.  It would be preferable if we could use
 the usual insertion operator (<<) to display a Fraction value.
 
Let's revisit our Coordinate class.  We would like to be able
 to write this:
cout << point << endl;And this should display the
Coordinate object named point on cout.
 Well, << is an operator just like + or *, and
 overloading those worked well, so we could add a method to class
 ostream overloading operator<< with a new definition
 to display a Coordinate value.  Then the compiler could treat
 an expression like
cout << pointas the call
cout.operator<<(point)However, this would require us to modify
ostream, a
 predefined, standardized class.  This is never a good idea,
 since the resulting class will no longer be standardized.  (It's also
 very hard to do.)
 We could define operator<< as a method of Coordinate, but C++ would then require us to invoke the method like
 so:
point << cout;Yikes! That looks like
cout is being sent to point---the complete opposite of what we want.  Technically,
 we could use the >> operator instead, but we'd still have the
 output stream on the right, and we're used to our streams on the far
 left.  Everyone keeps their streams on the left.
 Instead, we can overload the insertion operator (<<) as a
 normal function (i.e., not as a method) that takes an ostream (e.g., cout) and a Coordinate (e.g., point) as its operands.  That is, an expression
cout << pointwill be translated by the compiler as a normal function call
operator<<(cout, point)That's exactly what we want.
We define the following function in the header file, following the class declaration:
inline ostream & operator<<(ostream & out, const Coordinate & coord)
{
  coord.print(out);
  return out;
}
 There are several subtle points in this definition that need further explanation:
inline function.  Since it is not a method, defining it
   in the header file serves as both prototype and definition for the
   function.  An inline method must still be prototyped in the class
   so that the compiler fully understands that it is a member of the
   class.ostream which is altered by the operation---the Coordinate
   is inserted into the output stream.  Since it's changed, the ostream is a non-const reference parameter.const.cout <<The leftmostValue1<<Value2<< ... <<ValueN;
<< is applied first, and the value it returns
   becomes the left operand to the second <<.  Similarly, the
   value returned by the second << becomes the left operand of
   the third <<, and so on, down the chain.  Consequently, our
   function must return an ostream to its caller to make the
   chaining work correctly.  However, if we simply make the
   return-type ostream (instead of ostream&), the C++
   function-return mechanism will make and return a copy of
   parameter out which (as an alias for cout) would
   return a copy of cout for use by the next operator in the
   chain.  As a result, the next value would get inserted into a copy
   of cout, rather than cout itself, which would have
   unpredictable results.
   What we need is a way to tell the compiler to return the
   actual object to which out refers, instead of a copy of
   it.  This is accomplished by defining the function with a reference
   return-type, ostream&.  The compiler then does all the
   work to return the actual object itself (not a copy), and so the
   chaining will work as we want it to.
Coordinate
   is done by sending the Coordinate parameter coord
   the print() message we defined in Part I of this exercise,
   with out as its argument.  If we hadn't written print(), we could still define this function using the accessor
   methods getNumerator() and getDenominator().For our Fraction class, the specification of this operation is thus:
 
Specification:receive:out, anostream, andaFraction, aFraction.
precondition:==aFraction.getNumerator()nand==aFraction.getDenominator()d.
output:aFraction, in the formn/d, viaout.
passback:out, containingn/d.
return:out, for chaining.
Using this information, overload the output operator for class Fraction.  Uncomment the appropriate line in pierre2.cpp,
 and test it out.  You haven't written the input operator yet, so don't uncomment those lines yet.  Just use the default values in the
 Fractions.  Continue when pierre2 compiles and
 executes correctly (as far as it should for now).
 
As a dual to output, all of the things we learned about the output operator also apply to the input operator, just with a slight change in direction (reading information in, instead of sending it out). The syntax is very similar.
Suppose we wanted to input a Coordinate, entered as
(3,4)We could define this operator in the header file:
inline istream & operator>>(istream & in, Coordinate & coord)
{
  coord.read(in);
  return in;
}
 There are a few differences between the input and output (i.e.,
 extractor and insertion) operators:
 operator<<, the extraction
   operator is operator>>.istream
   instead of an ostream.Coordinate reference, rather than a
   const Coordinate reference.  Since we want to change this Coordinate, it cannot be const.istream reference
   instead of an ostream reference.  Similar to the output
   operator, this is for chaining: cin >> point1 >> point2;.Using this information, overload the extraction operator for class
 Fraction, so that a user can enter
3/4to input the fraction 3/4.
Uncomment the remaining statements in pierre2.cpp, and test
 the correctness of these operations.  Your Fraction class
 should now have sufficient functionality for Chef Pièrre to solve his
 problem using pierre2.
 
When everything in your Fraction class is correct, complete
 Fraction.doc.
 
While it is not necessary for this particular problem and the code solution we have, there are certain situations where it is useful for a function that is not a member of a class to be able to access the private instance variables. By default, C++ will not allow any other function to access private instance variables.
But suppose we had not written the read() method for class
 Coordinate, and wanted to overload operator>> in
 order to input Coordinate values.  We'd probably write what
 we do have for read() in the input operator:
istream & operator>>(istream & in, Coordinate & coord)
{
  char ch;
  in >> ch          // consume (
     >> coord.myX   // read x-coordinate
     >> ch          // consume ,
     >> coord.myY   // read y-coordinate
     >> ch;         // consume )
}
 Syntactically, this is 100% correct.  However, semantically, the
 compiler does not allow this and will generate compilation errors for
 the accesses to coord's instance variables.  As a non-method,
 this operator does not have the privilege of accessing the private
 instance variables.  However, we might like to be able to grant this
 permission.
 For such situations, C++ provides the friend mechanism.  If a class names a
 function as a friend with the keyword friend, then that
 non-member function is permitted to access the private section of the
 class.  A function is declared as a friend by including a prototype
 of the function preceded by the keyword friend in the class
 definition.  Thus, we would have to write this in our Coordinate class:
class Coordinate
{
  public:
    Coordinate();
    Coordinate(double x, double y);
    double getX() const;
    double getY() const;
    Coordinate operator+(const Coordinate & point2) const;
    friend istream & operator>>(istream & in, Coordinate & coord);
  private:
    double myX, myY;
};
 Placing the friend keyword before a function prototype in a
 class thus has two effects:
 
As we have seen in this exercise, an object-oriented programmer can
 usually find other ways to implement an operation without resorting
 to the friend mechanism.  In the object-oriented world,
 solving a problem through the use of methods is generally preferred
 to solving it through use of the friend mechanism.  As a
 result, friend functions tend to be used only when the
 object-oriented alternatives are too inefficient for a given
 situation.  Nevertheless, they are a part of the C++ language, and
 you should know the distinction between a method and a friend
 function of a class.
 
You could make a similar change to your Fraction class, even
 just prototype the input and output operators as friend
 functions, but it's not necessary.
 
Now that you have seen how to build a class, we need to expand our design methodology to incorporate classes:
Using this methodology and the C++ class mechanism, we can now create a software model of any object! If you can imagine it, you can write a class for it.
The class thus provides the foundation for object-oriented programming, and mastering the use of classes is essential for anyone wishing to program in the object-oriented world.
Learning to design and implement classes is an acquired skill, so feel free to practice by creating software models of objects you see in the world around you! You cannot practice this too much.
Turn in a copy of your code and sample executions of both
 drivers.  Answer the questions posed in this lab exercise in comments
 in the Fraction.doc documentation file.