Project Description
This project continues our simulation of tinker toy manufacturing and assembling.
In this project, you will modify and extend project 3.
Three new classes - TinkerToy, SquareToy and RodToy are introduced as part of
an inheritance hierarchy.
We've attempted to highlight the functional differences between project 3 and project 4 using
blue text and this image
It's possible we missed some, but we're confident you'll point them out to us :-)
In this project, we add two new kinds of tinker toys. SquareToys are similar to RoundToys
(they have color and holes), but obviously their shape is different. RodToys are used to
connect RoundToys and SquareToys (they fit in the holes) to create interesting shapes.
RodToys also have color, but no holes.
In this project you will be filling boxes (plural) with different kinds of tinker toys and shipping them to the
assembly plant in a truck. We will make round tinker toys with various diameters, colors and number of holes (as in project 3);
we will make square tinker toys with different dimensions (length of their sides), color and number of
holes; and we'll be making different colored RodToys of different lengths.
We will be filling multiple boxes with toys and placing them
in the truck and driving the truck to the assembly plant.
Our truck is especially made for UMBC -- it has unlimited capacity and never gets full.
The rules for making each kind of tinker toy are the same as in project 3, repeated here.
As noted in projects 2 and 3, these rules mean that only one type of tinker toy will be packed into a Box.
When making toys, one of three things may happen
- If a toy does not fit in the box currently being packed,
the box is sealed and placed on the Truck for delivery.
The toy is then placed in the next available box. Yes, it's possible that we will be shipping
empty boxes.
- If you run out of boxes, two messages are displayed.
One message tells how many toys were packed and the second indicates how many toys could not be
delivered. Both messages give the toy details (color, diameter, number of holes).
- If all requested toys have been manufactured, the current box being packed
is sealed and placed on the truck.
A message is displayed listing how many boxes (regardless of dimensions) could not be used and had to be destroyed.
These boxes are no longer available for future deliveries.
When determining if a toy fits in a box, use only the toy's volume as the determining factor. E.g. RodToys which
are longer than the box should still be packed if there is sufficient volume in the box.
As in previous projects, commands will be read and processed from a command file. The file will contain
modified commands that you processed in project 3.
As in project 3, your program will open the command file and loop until all commands found in the file have
been executed. All valid commands in the file are properly formatted, but you may encounter
invalid commands. See the Command File section below.
As you will see, many of the operations listed below appear to be quite similar to functions that were
specified in project 2. This is not a coincidence. One of our goals is for you to see the value of
writing reusable and/or easily modifiable code. This project gives you a chance to reuse and/or
modify code from project 2 and project 3..
The Classes
In this project, you will be implementing eight C++ classes -- RoundToy, Box and Truck, DeliveryLog, DeliveryRecord
from project 3 plus the new TinkerToy, SquareToy and RodToy classes.
The operations of each class are described below. Each operation is implemented as a single
public member function of the class. It's up to you to provide complete prototypes
(name, parameters (and how they are passed), return types and "constness" for
each public member function. No other public member functions are allowed, but
you may implement whatever private member functions you deem necessary.
None of the operations listed below read the command file.
All data members of all classes must be private
Toy class hierarchy
In this project we will be manufacturing different kinds of tinker toys -- RoundToys,
SqaureToys (really cubes) and RodToys (used by kids to connect tinker toys which have holes). To make
our code as generic as possible in anticipation of even more kinds of tinker toys, it is appropriate
for us to create a hierarchy of tinker toys. This hierarchy is shown in the diagram below.
TinkerToy class
This is an abstract base class which is the root of our hierarchy. It defines the minimum, common set
of operations that each kind of TinkerToy must support. The only common data element for all TinkerToys
is the color. The TinkerToy base class and all derived classes must support the following operations
- Volume(a pure virtual function) - returns the volume of a tinker toy
- Print (a pure virtual function) - prints the details of a tinker toy
- Clone (a pure virtual function) - creates a copy of a tinker toy (more on this below)
- Necessary constructor(s)
- Assignment operator
- virtual destructor
Spherical (Round) Tinker Toys
Spherical (aka Round) tinker toys are modeled using a C++ class named RoundToy.
In addition to the attribute(s) common to all tinker toys, a round tinker toy has the following
additional attributes.
- diameter - a floating point value
- number of holes - an integer
The RoundToy class supports the following operations. Note that the accessors for color, diameter
and number of holes are no longer required.
- Necessary constructors
- Assignment operator
- virtual destructor
- Operations required by the TinkerToy base class
SquareToy
A new kind of tinker toy is added to this project. The SquareToy class models tinker toys which are cubes
(all sides the same length) with holes. These toys and round toys are connected to make large models.
In addition to the attribute(s) common to all tinker toys, a square tinker toy has the following
additional attributes.
- side - an integer which is the measure of the length, width and height
- number of holes - an integer
The SquareToy class supports the following operations
- Necessary constructors
- Assignment operator
- virtual destructor
- Operations required by the TinkerToy base class
RodToy
A RodToy is another new kind of tinker toy. Kids use RodToys to connect SquareToys and RoundToys to create large models.
All RodToys are 1/4 inch in diameter. In addition to the attribute(s) common to all tinker toys, a RodToy has the following
additional attributes.
- length - an integer
The RodToy class supports the following operations
- Necessary constructors
- Assignment operator
- virtual destructor
- Operations required by the TinkerToy base class
Box
A box is modeled using a C++ class named Box. A box has the obvious attributes
of length, width and height which are integer values.
The Box class supports the following public operations
- The Box constructor that initializes the box with the specified length, width and height.
- A service that prints the box summary to the specified stream.
This service must be provided by overloading the output operator for the Box as in project 3.
The summary lists the number of toys in the box and all of their attributes.
Note that all toys in a box are identical.
- An accessor that returns the unused volume (available space) in the box.
- A service that stores a pointer to a tinker toy in the box.
A box might contain any one of the three kinds of tinker toys (RoundToy, SquareToy, or RodToy).
There are several ways to meet this requirement, however, for this project the Box must
contain a vector of pointers to dynamically allocated TinkerToys (the base class).
Using these pointers not only allows us to store any kind of toy in the box, but also
provides polymorphism when a TinkerToy member function (eg. Volume, Print) is called
and paves the way for new kinds of tinker toys in the future without having to change code in the Box.
tinker toys should be allocated in main( ).
Because the Box now contains pointers to dynamically allocated memory, it is necessary to implement
the assignment operator, copy constructor and destructor for the Box class. The assignment operator and copy constructor
require the use of the Clone( ) function. Cloning is described in more detail below and will be discussed in class.
The Command File
The command file has the following format. You may assume that valid commands
are properly formatted and all data elements are the appropriate type.
You may not assume all commands are valid.
- The first line of the command file contains an integer (let's call it N), which tells how many
colors of RoundToys we'll be manufacturing.
- The next N lines contain the names of the colors (one per line without spaces). Color names are guaranteed to be
unique.
- Each non-blank line contains one of the following commands. Any command may
appear in the file multiple times (or not at all) and the commands may appear in any order.
- TOYS type count color <other attributes>
This command directs your program to produce the specified tinker toy
where type is one of "Round", "Square" or "Rod", count is an integer, and color is a string.
You may assume that the color matches on of the N colors read previously from the file.
If type is "Round", then <other attributes> will be the number of holes (integer) and the diameter (float)
If type is "Square", the <other attributes> will be the number of holes (integer) and the length of each side (integer)
If type is "Rod", the <other attributes> will be the length of the RodToy (integer). Recall that all rods are 1/4 inch
in diameter.
- BOXES count length width height
Where all parameters are integers.
This command informs your program that count boxes with the specified dimensions have been
delivered and are ready to be filled with Toys
- PRINT
This command instructs your program to print the detailed Truck information
as described above
- DELIVER miles destination
This command instructs your Truck to drive the specified number of miles
to the specified destination, then unload its contents and return
to the manufacturing site for more boxes. In this command, miles is an integer and destination is the name
of an assembly plant (which may contain spaces).
Cloning
When a class like Box contains a pointer(s) to a base class (like TinkerToy) an important issue arises when we wish
to make a copy of a Box using the assignment operator or copy constructor.
As we've learned, because Box contains a pointer to dynamically allocated memory (the TinkerToy)
Box's copy constructor must allocate memory and copy the contents of
the allocated memory pointed to by the pointer in the existing Box into the memory allocated in the new Box (a "deep" copy).
The problem is that since the Box has TinkerToy pointers (pointers to the base class) and not RoundToy/SqaureToy/RodToy pointers,
we don't know if these pointers point to RoundToys, SquareToys or RodToys,
so we don't know which copy constructor to call to initialize the newly allocated memory.
The solution is to write a virtual Clone( ) function for each derived toy class. This function is called by
the copy constructor and assignment operator (using the base class pointer in the parameter object) and the Clone( )
function is called for the appropriate derived toy via polymorphism.
What does the Clone( ) function in the derived class do? It returns a pointer to newly allocated RoundToy/SquareToy/RodToy
toy created by the appropriate RoundToy/SquareToy/RodToy copy constructor! This pointer is then stored in the new Box object.
In essence, the Clone( ) function gives us an indirect, polymorphic path to the appropriate copy constructor.
Check out this website for some example code.
Other Project Requirements
- In the event that a command file contains consecutive BOXES commands, boxes must be filled
in the order delivered (i.e. first in, first out).
- One good way to insure that you have properly implemented the Box constructors, destructor and assignment
operator is to monitor the creation and destruction of TinkerToy objects. To accomplish this task, your
project must provide the following functionality.
- Provide a static data member of the TinkerToy class that is incremented each time
a new TinkerToy is created.
- Provide a static data member of the TinkerToy class that is incremented each time
a TinkerToy is destroyed.
- Provide public static accessors in the TinkerToy class for these counters.
- As the very last thing in main, print the values of these counters with appropriate labels.
In a real life, properly written application, we would expect that these counters have the same values since
every dynamically allocated TinkerToy object should be destroyed to avoid memory leaks.
When reported in our project, however, these values may be the same or may be different
even if your implementation is correct. Whether the values are reported as the same or not
depends on the command file used when your program is run.
For 10 points extra credit explain why these values might be different.
In particular explain
- How the command file determines if the values are the same or different.
- What's going on in your code that might make the values be different. Be VERY SPECIFIC.
Submit your extra credit answers with your project code in a file named ExtraCredit.txt.
- As in project 3 and as shown in the sample output below, your program must print a summary
that include the total number of toys produced and the number of toys
of each color produced. This summary must be in tabular format
(right-justified columns) with 5 toy colors per line.
- As usual, your output need not look exactly like the sample output below.
However, the output for each box (box number, number of toys and toy color) must
appear in right-justified columns as shown in the sample output.