# Lab 11: Building Classes

## Introduction

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:

1. Pièrre frequently must prepare a dish for more or fewer than 12 customers, requiring the scaling of his recipes (e.g., 1 customer results in 1/12 of a recipe, 2 customers results in 1/6 of a recipe, 15 customers results in 15/12 = 5/4 of a recipe, etc.).
2. Pièrre's recipes are written using fractions (e.g., 1/2 tsp., 3/4 cup, etc.) so that he must multiply fractions when scaling a recipe.
3. Pièrre is so poor at multiplying fractions, that he has hired us to write a program that will enable him to conveniently multiply two fractions.

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.

## Files

Directory: `lab11`

Create the specified directory, and copy the files above into the new directory. Only `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.

## Looking at the Code

Take a moment to compare the programs in `pierre1.cpp` and `pierre2.cpp`. Both programs implement the same basic algorithm:

1. Get `oldMeasure`, the fractional measure to be converted.
2. Get `scaleFactor`, the fractional conversion factor.
3. Compute `newMeasure` = `oldMeasure` * `scaleFactor`.
4. Output `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.

## Creating Classes

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

1. Defining the data objects, known as instance variables, that make up the attributes of an object of the new type.
2. Surrounding those definitions with a class structure.

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 `pointI` has two `double` 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:

```class `TypeName`
{
public:

private:
`Type1` `InstVarList1`;
`Type2` `InstVarList2`;
...
`TypeN` `InstVarListN`;
};```
where each `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/4```
Each fraction has the form:
``number1`/`number2``
where `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`:

• Write a class definitions for a class named `Fraction`.
• In the appropriate place, define two integer instance variables named `myNumerator` and `myDenominator`.
Look at the patterns and example above for help with these two steps.

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.

## Methods

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.

### Class Structure and Information Hiding

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.

### Methods As Messages

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 `string`s.

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.

## Part I: `pierre1.cpp`

In this first part of this exercise, we will focus on adding the methods to class `Fraction` needed to get `pierre1.cpp` operational.

### An Output Method

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:
receive: `out`, an `ostream` to which I write my values.
output: `myX` and `myY`, as an ordered pair.
passback: `out`, containing the output values.
Note the use of internal perspective (e.g., "...I write my value.").

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: If `point` is a `Coordinate` object whose x-coordinate is 3 and whose y-coordinate is 4, then what does the statement `point.print(cout);` display?

Question #11.2: If `origin` is a `Coordinate` object whose x-coordinate is 0 and whose y-coordinate is 0, then what does the statement `origin.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.

### Constructors

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 and `myY` == 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:

````ClassName`::`ClassName`(`ParameterList`)
{
`StatementList`
}```
where the first `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:
postcondition: `myNumerator` == 0 and `myDenominator` == 1.
That is, the definition:
`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 Second Constructor

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: `x` and `y`, two `double` values.
postcondition: `myX` == `x` and `myY` == `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:
receive: `numerator` and `denominator`, two integers.
precondition: `denominator` is not 0.
postcondition: `myNumerator` == `numerator` and `myDenominator` == `denominator`.
Consequently, the definitions
```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`.

### Accessor Methods

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:
return: my x-coordinate.
and
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()` and `point2.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:
return: `myNumerator`.
Also write an accessor method `getDenominator()` that satisfies this specification:
Specification:
return: `myDenominator`.
Since these are simple methods, define them `inline` following the class declaration in the header file. Test their syntax by compiling the code and continue when they are correct.

### Input

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`, an `istream.`
precondition: `in` contains a `Coordinate` of the form `(x,y)`.
input: `(x,y)`, from `in`.
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 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 '('
}```

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;
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`, an `istream`.
precondition: `in` contains a Fraction value of the form `n/d` and `d` is not zero.
input: `n/d`, from `in`.
passback: `in`, with `Fraction` `n/d` extracted from it.
postcondition: `myNumerator` == `n` and `myDenominator` == `d`.

Some differences from the `read()` of `Coordinate`:

• You can (and should) test the second half of the precondition (i.e., `d` is not zero). Use a call to `assert()`.
• Watch the punctuation. A coordinate has three punctuation characters, but a fraction has just one. Don't blindly copy the input statement. Change the comments so that it's clear what's being read in by each input operator.

After you've written and successfully compiled this new method, you should be able to uncomment the statements:

```oldMeasure.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.

### Fractional Multiplication

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 + point2`
is 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.myX` and `result.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 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 + point2`
to 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 * scaleFactor`
can 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:

• 1/2 * 2/3 = 2/6 = 1/3
• 3/4 * 2/3 = 6/12 = 1/2
We multiply the numerators together and the denominators together, and then we simplify.

The specification for such an operation can be written as follows:

Specification:
receive: `rightOperand`, a `Fraction` operand.
return: `result`, a `Fraction`, containing the product of the receiver of this message and `rightOperand`, 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:

1. Find `gcd`, the greatest common divisor of `myNumerator` and `myDenominator`.
2. Replace `myNumerator` by `myNumerator/gcd`.
3. Replace `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: `myNumerator` and `myDenominator` do 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.

## Part II. `pierre2.cpp`

In 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.

### Output Revisited

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";```
`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 << point`
as 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 << point`
will 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:

• Because the function is simple, we define it in the header file as an `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.
• When we invoke this function, the left operand is an `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.
• When we invoke this function, the type of the right operand is the type of the object we want to display, and this object does not change. Since it's not primitive, we pass it by reference; since it does not change, we pass it `const`.
• We want to chain objects in a output statement:
`cout << `Value1` << `Value2` << ... << `ValueN`;`
The leftmost `<<` 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.

• The actual work of formatting and outputting the `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`, an `ostream`, and `aFraction`, a `Fraction`.
precondition: `aFraction.getNumerator()` == `n` and `aFraction.getDenominator()` == `d`.
output: `aFraction`, in the form `n/d`, via `out`.
passback: `out`, containing `n/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 `Fraction`s. Continue when `pierre2` compiles and executes correctly (as far as it should for now).

### Input Revisited

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)
{
return in;
}```
There are a few differences between the input and output (i.e., extractor and insertion) operators:

• The insertion operator is `operator<<`, the extraction operator is `operator>>`.
• The left operand of the extraction operator is an `istream` instead of an `ostream`.
• The right operand is a `Coordinate` reference, rather than a `const` `Coordinate` reference. Since we want to change this `Coordinate`, it cannot be `const`.
• The function returns a reference to an `istream` reference instead of an `ostream` reference. Similar to the output operator, this is for chaining: `cin >> point1 >> point2;`.
This operation is sufficiently simple to define inline within the header file.

Using this information, overload the extraction operator for class `Fraction`, so that a user can enter

`3/4`
to 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`.

## Part III: Friend Functions

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 (
>> ch          // consume ,
>> 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:

• It tells the compiler that the function is not a member of the class.
• It tells the compiler that a definition of that function is nevertheless permitted to access the private section of the class.

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.

## Object-Centered Design Revisited

Now that you have seen how to build a class, we need to expand our design methodology to incorporate classes:

1. Describe the behavior of the program.
2. Identify the objects in the problem. If an object cannot be directly represented using available types, design and implement a class to represent such objects.
3. Identify the operations needed to solve the problem. If an operation is not predefined:
1. Design and implement a function to perform that operation.
2. If the operation is to be applied to a class object, design and implement the function as a method (or a friend function).
4. Organize the objects and operations into an algorithm.

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.

## Submit

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.

## Terminology

accessor method, attribute, class, construct (an object), construct, friend mechanism, inline method, instance variable, internal perspective, message, method, object-oriented programming, overloading, postcondition, private, public, reference return-type, scope operator