UMBC CMSC 202
UMBC CMSC 202 CSEE | 202 | current 202

CMSC 202 Fall 2004
Project 4

Inheritance and Polymorphism

Assigned Mon Nov 8th, 2004
Design Due Sunday Nov 14 at 11:59pm
Program Due Sunday Nov 28 at 11:59pm
Note: The originally scheduled due date was Wednesday Nov 24th (the day before Thanksgiving).
The new due date is now the Sunday after Thanksgiving.
Be advised that little or no help will be available after the 24th.
Updates Nov 10
The original PD stated that for the RoundToy, "Note that the accessors for color, diameter and number of holes are no longer required or permitted." This has been changed.
While these accessors are no longer required (and shouldn't be used outside the RoundToy class) they will be permitted so that you don't have to spend time removing them.

Objectives


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

  1. 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.
  2. 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).
  3. 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
  1. Volume(a pure virtual function) - returns the volume of a tinker toy
  2. Print (a pure virtual function) - prints the details of a tinker toy
  3. Clone (a pure virtual function) - creates a copy of a tinker toy (more on this below)
  4. Necessary constructor(s)
  5. Assignment operator
  6. 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.
  1. diameter - a floating point value
  2. 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.
  1. Necessary constructors
  2. Assignment operator
  3. virtual destructor
  4. 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.
  1. side - an integer which is the measure of the length, width and height
  2. number of holes - an integer
The SquareToy class supports the following operations
  1. Necessary constructors
  2. Assignment operator
  3. virtual destructor
  4. 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.
  1. length - an integer
The RodToy class supports the following operations
  1. Necessary constructors
  2. Assignment operator
  3. virtual destructor
  4. 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
  1. The Box constructor that initializes the box with the specified length, width and height.
  2. 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.
  3. An accessor that returns the unused volume (available space) in the box.
  4. 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.

Truck

The Truck is modeled using a C++ class named Truck. The Truck is unchanged from project 3. Our specially made truck has infinite capacity and never gets full. The Truck will be delivering boxes to multiple assembly plants. The Truck supports the following operations.
  1. The truck default constructor
  2. A service that delivers the Truck's contents to an assembly plant.
  3. A service that loads a box onto the truck. This service must be provided by overloading the += operator for the Truck
  4. A service that prints the Truck's current load and delivery log. This service must be provided by overloading the output operator for the truck as in project 3. This output contains the following information. See the sample output below.
    1. Current Load - the number of boxes and summary of the contents of each box currently on the truck waiting for delivery.
    2. Delivery Log - A list of all deliveries, including the assembly plant name, the number of miles and the number of boxes delivered.
  5. A service that adds a new DeliveryRecord to the Truck's DeliveryLog. This service must be implemented by overloading the += operator for the Truck.

DeliveryRecord

This class represents the details of a single delivery of boxes. The attributes of this class include the name of the assembly plant to which the delivery was made, total miles traveled to and from the assembly plant and the number of boxes delivered. The DeliveryRecord is unchanged from project 3. You may choose to use remove the dynamically allocated data members and associated member functions
  1. Necessary constructors
  2. A service to print a DeliveryRecord in a format similar to that in the sample output. This service must be implemented by overloading the DeliveryRecord's output operator as a friend function

DeliveryLog

A DeliveryLog is a set of DeliveryRecords kept in the order in which deliveries are made. Each Truck keeps a DeliveryLog so it can report its delivery activity details. The DeliveryLog supports the following operations. The DeliveryLog is unchanged from project 3.
  1. A default constructor
  2. A service to add a new DeliverRecord to the DeliveryLog.
  3. A service to print the contents of the DeliveryLog in a format similar to that found in the sample output. This service must be implemented by overloading the DeliveryLog's output operator as a friend function.

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.

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

  1. 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).
  2. 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.
    1. Provide a static data member of the TinkerToy class that is incremented each time a new TinkerToy is created.
    2. Provide a static data member of the TinkerToy class that is incremented each time a TinkerToy is destroyed.
    3. Provide public static accessors in the TinkerToy class for these counters.
    4. 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
    1. How the command file determines if the values are the same or different.
    2. 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.
  3. 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.
  4. 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.

Sample Output

This sample output is provided to show you a reasonable output format which satisfies the project requirements. It is not necessary that you follow this format exactly, but whatever format you choose must provide all required information. Toy details must be in tabular format. Note that the use of tabs will make the columns left-justified. This output was created from the command file Proj4Cmds.dat found in Mr. Frey's public directory. CMD BOXES: 15, 5, 6, 7 CMD TOYS: Round, 340, 3.50, DkBlue, 2 No more boxes 135 DkBlue Round toy(s) packed 205 DkBlue Round toys(s) not packed CMD BOXES: 1, 2, 3, 4 CMD TOYS: Rod, 100, 5, DkGreen No more boxes 97 DkGreen Rod toy(s) packed 3 DkGreen Rod toys(s) not packed CMD BOXES: 5, 2, 3, 4 CMD TOYS: Square, 5, 1, Lime, 2 All toys made and shipped 4 boxes destroyed CMD PRINT Current Load: 17 boxes Box # 1 9 DkBlue Round Toy(s) with diameter 3.50 and 2 holes Box # 2 9 DkBlue Round Toy(s) with diameter 3.50 and 2 holes Box # 3 9 DkBlue Round Toy(s) with diameter 3.50 and 2 holes Box # 4 9 DkBlue Round Toy(s) with diameter 3.50 and 2 holes Box # 5 9 DkBlue Round Toy(s) with diameter 3.50 and 2 holes Box # 6 9 DkBlue Round Toy(s) with diameter 3.50 and 2 holes Box # 7 9 DkBlue Round Toy(s) with diameter 3.50 and 2 holes Box # 8 9 DkBlue Round Toy(s) with diameter 3.50 and 2 holes Box # 9 9 DkBlue Round Toy(s) with diameter 3.50 and 2 holes Box # 10 9 DkBlue Round Toy(s) with diameter 3.50 and 2 holes Box # 11 9 DkBlue Round Toy(s) with diameter 3.50 and 2 holes Box # 12 9 DkBlue Round Toy(s) with diameter 3.50 and 2 holes Box # 13 9 DkBlue Round Toy(s) with diameter 3.50 and 2 holes Box # 14 9 DkBlue Round Toy(s) with diameter 3.50 and 2 holes Box # 15 9 DkBlue Round Toy(s) with diameter 3.50 and 2 holes Box # 16 97 DkGreen Rod(s) with length 5 Box # 17 5 Lime Square Toy(s) 1 x 1 x 1 with 2 holes Delivery Log ------------ No Deliveries CMD DELIVER 5 My Assembly Plant Toy production summary: 237 toys 0 Red 0 White 0 Blue 0 Green 0 Orange 0 Pink 0 LtBlue 135 DkBlue 0 LtGreen 97 DkGreen 5 Lime 0 Yellow TinkerToy Constructor called 857 times TinkerToy Destructor called 857 times

Free Advice and Information

  1. THINK about this project before coding. Be sure you understand the relationships among the objects.
  2. Complete the project without writing Box's copy constructor and assignment operator. Your output should look correct, but of course you'll have a massive memory leak.
  3. Functions called from main that are not part of any class are permitted. If you create new functions, their prototypes must be found in Proj4Aux.h and they must be implemented in Proj4Aux.cpp; you must modify the makefile provided to account for these new files.
  4. Your program must provide adequate error checking similar to project 3.
  5. Use incremental development !!!!!
  6. Expect to use/modify code from this project in project 5. Design and code accordingly.
  7. Mr. Frey's public directory for this project is /afs/umbc.edu/users/d/e/dennis/pub/CMSC202/p4.

Project Design Assignment

Your project design document for project 4 must be named p3design.txt. Be sure to read the
design specification carefully. Submit your design in the usual way.

Project Makefile

You must provide the makefile for this project. Use the makefile from project 3 and modify it appropriately. If you don't change the names of the files from project 3, the changes will be minimal.

The graders will be typing the command make Proj4 when they grade your project. This command must cause all .cpp files to be compiled and the executable named Proj4 to be created.

The make utility can also be used for compiling a single program without linking. For example, to compile Box.cpp, type make Box.o.

In addition to compiling and linking your files, make can be used for maintaining your directory. Typing make clean will remove any extraneous files in your directory, such as .o files and core files. Typing make cleanest will remove all .o files, core, Proj4, and backup files created by the editor. More information about these commands can be found at the bottom of the makefile.


Grading

The grade for this project will be broken down as follows. A more detailed breakdown will be provided in the grade form you receive with your project grade.

85% - Correctness

This list may not be comprehensive, but everything on this list will be verified by the graders.

15% - Coding Standards

Your code adheres to the CMSC 202 coding standards as discussed and reviewed in class.
In particular, since this is your first C++ program using classes, pay attention to the list below. Graders will check all applicable items in the coding standards.
  1. Your class implementation and class usage
  2. Proper use of const
  3. Your function header comments (particularly pre- and post-conditions)
  4. In-line comments
  5. Code readability

Project Submission

Submit your project in the usual way.

More complete documentation for submit and related commands can be found here.

Remember -- if you make any change to your program, no matter how insignificant it may seem, you should recompile and retest your program before submitting it. Even the smallest typo can cause compiler errors and a reduction in your grade.

Avoid unpleasant surprises!

Be sure to use the submitmake and submitrun utilities provided for you to compile, link and run your program after you've submitted it.


Last Modified: Wednesday, 10-Nov-2004 19:48:18 EST