Lab 8
Preparing to Ship Sheared Sheep
Introduction
============
In the previous lab, we practiced sorting arrays. This time we are
going to practice using classes and objects. The next, and final,
lab will see the construction of a large scale application which
will use both classes and sorting techniques.
Lab 8-1 (Guided)
================
When we last left our intrepid heroes, they had just given the
Etruscan programmers the task of figuring out how to store complex
information in a program. Namely, they wanted to be able to store
records for an entire sheep, and to sort the sheep so they could
ship the sheep to where they need to go.
The ancient programmers worked hard! They sent emissaries out into
the world and traveled to the corners of the Mediterranean. While
the travelers were gone, one of their programmers discovered that
he could use multiple arrays to store complex records, but this
proved to be very unwieldy. When he tried to sort them, everything
fell apart. So, they waited until their brethren returned. Sadly,
of the 4 that left, only 1 returned. No one knows what became of
the other 3 programmers, but there is a very ancient line of people
on the Isle of Crete who have a strange obsession with LISP, so we
like to think that at least one of them survived.
At any rate, one of them did make it back. He had been to Greece
and he had heard a teacher by the name of Socrates speaking about
something called the "Theory of the Forms*." In this theory,
Socrates taught that everything in the world fit into a hierarchy,
where each layer of the hierarchy represented different levels of
abstraction. Thus people could speak of "Tree" as an abstract and
see a specific tree as a shadow of "Tree".
At first the other programmers thought that the young man was
insane, which he may well have been, but that isn't the point. The
point is that they soon realized that the ability to encapsulate
ideas into abstractions was the answer they sought. They could
write a small piece of code which contained all the information of
the sheep's record, and then they could add behavior to that. Even
better, they would be able to create a special container which they
could store the sheep objects in. This container would represent
the ship, and they could use this abstraction to think in terms of
what the problem actually was. Rather than putting 5 records at
some index into dozens of different arrays, they could think of
"ship.loadSheep(sheep)" which was a lot clearer as to its intent.
So they set out to learn what each of these containers should do.
Their initial attempts were terribly complicated as they made the
common mistake of trying to implement everything that went into making
a ship a ship and a sheep a sheep. Surely ships and sheep could be
expressed more easily. Eventually, one of the programmers had a
break through. "My brothers! Here me!" (The rest of the team
snickered at his purple prose, but they listened.) "Why don't we
just implement the parts of the ship and sheep we are interested in?"
The rest of the team thought this was a bangup idea, and so they
decided on the following items for the ships:
Data
----
A list of sheep. There can be at most 10 sheep in a ship.
The number of sheep currently on the ship.
Behavior
--------
load a sheep onto the ship
unload a sheep from the ship
count the sheep
print out the list of sheep
determine if the ship is full or not.
The team who was working on the sheep came up with the following
items for the sheep.
Data
----
Sex (M or F)
Nationality (Etruscan, Jewish, or Greek)
Destination (Any country in the world)
Cost (Sistersi, stored in Indian number format)
Shearing Status (has the sheep been sheared or not)
Color (Any color)
Behaviors
---------
The ability to get or set all of the above attributes.
The ability to pretty print the sheep's data. (a print sheep
function)
The ability to convert the sheep's data into a string.
Having congratulated themselves on a good design, they set out to
build the system.
* For a treatment of Socrates's theory, take a look at "The Republic"
(most notably the allegory of the cave) and Meno. You can get
both online for free as the copyright expired over a thousand
years ago. Head over to
http://www.gutenberg.net for
enlightenment. You'll want to search for "Plato" as the author
because Socrates was the teacher, and Plato wrote down what Socrates
said.
Procedure
=========
We will follow along with the first part of the system, which is the
construction of the ship. The programmers decided that until they
had the sheep class ready to go, they would implement the sheep as
integers. They came up with the following header which they put
into a file called sheepShip.h:
-- Begin sheepShip.h --
// A small class for the storage of sheep on a ship.
#ifndef SHEEPSHIP_H
#define SHEEPSHIP_H
class sheepShip {
public:
// Constructors
sheepShip();
// Destructors
~sheepShip();
//methods
//puts a sheep on the ship
bool loadSheep(int sheep);
//unloads a single sheep from the ship
int unloadSheep();
//returns the number of sheep on the ship
int sheepCount();
//prints the list of sheep on the ship
void printSheep();
//returns true if the ship is full, false otherwise
bool isFull();
private:
int sheepHold[10];
int count;
};
#endif
-- end sheepShip.h --
The implementation file was placed into a file named sheepShip.cpp:
-- begin sheepShip.cpp --
#include <iostream>
#include "sheepShip.h"
//constructor
sheepShip::sheepShip() {
//the ship starts with no sheep
count = 0;
}
//destructor
sheepShip::~sheepShip() {
//do nothing (for now)
}
//puts a sheep on the ship
bool
sheepShip::loadSheep(int sheep) {
//full sheep ship! Ship it out!
if(count == 10)
return false;
sheepHold[count++]=sheep;
return true;
}
//unloads a single sheep from the ship
int
sheepShip::unloadSheep() {
//empty hold! No sheep
if(count==0)
return 0;
//unload and return the sheep
return sheepHold[--count];
}
//returns the number of sheep on the ship
int
sheepShip::sheepCount() {
return count;
}
//prints the list of sheep on the ship
void
sheepShip::printSheep() {
int i;
for(i=0; i<count; i++) {
std::cout << sheepHold[i] << std::endl;
}
}
//returns true if the ship is full, false otherwise
bool
sheepShip::isFull() {
return count==10;
}
--end sheepShip.cpp--
Finally they constructed a driver which would read in ten sheep and
place them on their ship:
--begin shipTest.cpp--
#include <iostream>
#include "sheepShip.h"
using namespace std;
int main(void) {
int sheep;
sheepShip ship;
//fill up the ship
while(!ship.isFull()) {
//get a sheep from the user
cout << "Sheep: ";
cin >> sheep;
//load the sheep on the ship
ship.loadSheep(sheep);
//print the current number of sheep
cout << "There are " << ship.sheepCount()
<< " sheep on the ship." << endl;
}
//print the shipping manifest
cout << "Shipping Manifest" << endl;
ship.printSheep();
//unpack the ship
cout << endl << "Unloading Order" << endl;
while(ship.sheepCount()) {
sheep = ship.unloadSheep();
cout << sheep << endl;
}
}
--end shipTest.cpp--
Finally they constructed a makefile to ease the building process:
--begin Makefile--
all: shipTest
shipTest: sheepShip.o shipTest.o
g++ -o shipTest shipTest.o sheepShip.o
shipTest.o: shipTest.cpp
g++ -c shipTest.cpp
sheepShip.o: sheepShip.cpp sheepShip.h
g++ -c sheepShip.cpp
--end Makefile--
Your first task is to create all the files listed above and then get
it working. Once you're able to run shipTest, take a moment to
pause and reflect on how this program works. Look at it until you
understand every last peace of it. You'll have to, because in the
next section, you will be altering it!
Lab 8-2 (self)
==============
We have accomplished half the task before us. We have a ship class
and ship objects. Now we have to modify all this to handle sheep
correctly.
1. Create a sheep class. The class definition and implementation
is up to you, but it should only contain the features described
in lab 8-2.
2. Modify the sheepShip so that it stores sheep. Note that you'll
have to include sheep.h in your header and in your
implementation file. Also, you'll have to alter the following
functions (both prototypes and definition):
loadSheep
unloadSheep
printSheep
3. Modify the shipTest program so that instead of inserting and
printing integers, it inserts and prints sheep. Also, you'll
have to make it read in details about the sheep. So the code
will get just a little bit longer.
Hints
-----
- Try to identify where you want to pass objects by references.
Also, consider writing your own copy constructor.
- The sheep class is very similar, in nature at least, to the phone
records we did in class.
- You'll also have to modify the makefile to be able to use the
sheep. You'll want to add a sheep.o entry.