Project 4
Inheritance and Polymorphism
with Shapes
Assigned |
March 31, 2003 |
Design Due
| Sunday April 6, 2003, 11:59pm
|
Program Due |
Sunday April 13, 2003, 11:59pm |
Updates |
03 April 2003, 3:40pm
A couple of students have asked if it's okay to have
a vector of Shape pointers for each different type of Shape,
or is it a requirement to have just one vector of Shape
pointers (that gets passed to DrawShapes().
You are required to have only one vector of Shape pointers.
Here's why...one reason is practical, the others are just good design
- One measure of how good a program design is is its extensibility.
That means how well can this program handle changes to the type of inputs,
and/or the range of inputs and/or other similar unforseen situations.
A program that has one vector of Shape pointers for each type of
shape will require more modifications than a program with just one vector of
shape pointers when a new shape is added to the input file and is therefore
less extensible and therefore a poorer design.
- Having a vector of Shape pointers for each type of shape
means that there's no real need for the shapes to have an identity,
or at least no need for your code to use the identity, since the vector determines
the type and therefore the identity, making DrawShapes() potentially
less polymorphic.
- On the practical side, we desire that your program "draw" shapes in
the same order in which they were read from the input file. This is
only possible if only vector of shape pointers is used.
01 April 2003, 4:40pm
A couple of students asked whether it was okay to check for
invalid data such as a negative radius in main() when the file
is being read.
Yes, that's generally a good idea, but.....
- As the implementer of a class, you cannot depend on the user
of your class to verify their data. Therefore, good defensive
programming dictates that your class should check the data anyway.
- To gain experience with exceptions in this project, you need
to construct ill-formed shapes.
So, bottom line -- don't validate the input in main(), but
rather construct the shapes regardless of the data and let the member
functions throw exceptions.
|
Objectives
- To gain experience modifying existing code
- To gain experience designing and implementing derived classes
- To gain experience writing polymorphic code
Project Description
In this project, you will reuse code from projects 2 and 3 (your Point class),
implement classes already designed for you, and you will design and implement
derived classes based on their descriptions below.
In this project you will also create exception classes to be thrown by some
of your class' methods and caught by their callers.
The various shape classes are shown in the inheritance heirarchy diagram below.
Shape, Circle and Rectangle (and their associated exception classes)
have defined for you in their respective .H files
found in Mr. Frey's public directory for this project. You may not change these
files. Although you may wish to copy these files temporarily to your
working directory, your makefile should reference these files and they should
not be submitted.
In this project, you will read information about various shapes from
an input file, instantiate new shapes with
the required attributes, and then "draw" all the shapes using a polymorphic function.
Your main( ) should perform the usualy command line argument verification,
open the input file, read the shape information from the file, instantiate each shape
and then print all the shapes. Be sure to delete any and all dynamically allocated
memory so there are no memory leaks.
The command line will have just one argument -- the name of the input file.
Class Definitions
The Shape Class
The Shape class is an abstract class which is at the top of the inheritance
heirarchy. It is defined for you in Shape.H in Mr. Frey's public directory.
You may not change this file. You must implement the Shape class in Shape.C.
The Circle Class
The Circle class is derived from the Shape class. It is defined for you in
Circle.H in Mr. Frey's public directory. You may not change this file.
You must implement the Circle class in Circle.C. Note that the Circle
class has a private data member for PI. Intialize this data member to 3.14159.
The Rectangle Class
The Rectangle class is derived from the Shape class and defined in Rectangle.H
in Mr. Frey's public directory. You may not change this file.
You must implement the Rectangle class in Rectangle.C
The Cylinder Class
A cylinder is a 3-dimensional object with a circular base and "sides" which
are perpendicular to the base. Its 3rd dimension is the length of the sides, usually
known as it's height. The Cylinder class should be (and must be) derived from
the Circle class. You must design and implement the Cylinder class. It's definition
will be in Cylinder.H and it's implementation in Cylinder.C.
The Ring Class
A ring is a 2-dimensional shape formed by two concentric circles with different radii.
The picture below shows a ring.
The area of the ring is represented by the shaded portion of the picture.
The Ring class should be (and must be) derived from the Shape class.
You must design and implement the Ring class. It's definition will be in
Ring.H and it's implementation in Ring.C.
The Sphere Class
A sphere is a 3-dimensional circle (a ball). In addition to the area and
circumference of the underlying circle, the sphere also has volume and
surface area.
The Sphere should be (and must be) derived from the Circle class.
The Point Class
The Circle and Rectangle classes both use Point objects in their definition.
You should reuse your Point class from project 2 or project 3.
Note that Circle.H
and Rectangle.H both #include Point.H so it may be
necessary to rename your file.
The Polymorphic Function
After the file has been read and all shapes have been created, you must use
the polymorphic function DrawShapes( ) to "draw"
all of the shapes your project has created.
All shapes are created, then all are "drawn"
You cannot use this function to draw one shape at a time.
Since we cannot actually draw shapes, we will interpret "draw" to mean
"print out relevant information about the shape". This "relevant information"
is described below in the sample output section.
The prototype for this function is
void DrawShapes( const vector< const Shape* >& shapePtrs);
and cannot be changed. This function may be included in Proj4.C
Exceptions
Each shape has a method to draw itself and/or one or more methods which
performs a calculation. For example, the Circle
class provides a method for calculating its area and another for
calculating its circumference.
Each of these methods requires that the radius of the circle be positive, otherwise the
circle is not well formed. When methods such as these detect an ill-formed shape,
these methods should throw an exception to be caught by the caller.
Exception classes for the Circle and Rectangle classes have been defined
for you. Use them as a model for exception classes for your shapes.
It is not necessary to throw exceptions from your constructors.
The Input File
The input file will contain one line of data for each shape to be created.
The data items on each line will be separated by one or more spaces.
The file may contain blank lines.
If a line is not blank, you may assume that the data is in the correct
order and that each data item is of the appropriate type as described below.
The first data item on each line will be the type of shape to create.
The data item will be one of the following (without the quotes), all in lowercase
-- "circle", "cylinder", "rectangle", "ring", "sphere"
The remaining data items on the line will depend on the shape type.
- If the shape type is circle or sphere the remaining data items are
- integer x-coordinate of the center
- integer y-coordinate of the center
- floating point radius
- If the shape type is cylinder the remaining data items are
- integer x-coordinate of the center
- integer y-coordinate of the center
- floating point radius
- floating point height
- If the shape type is rectangle the remaining data items are
- integer x-coordinate of the lower left corner
- integer y-coordinate of the lower left corner
- integer x-coordinate of the upper right corner
- integer y-coordinate of the upper right corner
- If the shape type is ring the remaining data items are
- integer x-coordinate of the center
- integer y-coordinate of the center
- floating point inner radius
- floating point outer radius
Sample Output
The sample output below was produced by processing the file named proj4.dat
found in Mr. Frey's public directory. Although your output does not have to
match exactly, the following output requirements must be met and all data fields
shown below must be present.
- All floating point values must be output with 4 decimal places and
right justified in a field of 10 characters. This should cause the
decimal places to align nicely.
- Points must be formatted as in projects 2 and 3; i.e. enclosed in parenthesis
with coordinates separated by commas.
- All labels must be followed by a colon. All colons must be vertically aligned.
- All output must be labelled with the shape's type.
- All headings must be underlined as shown in the sample output
All characters in the heading must be underlined
and there may be no extraneous underlining. The following are NOT acceptable.
This is my heading
This is my heading
-----------
------------------------
linux1[5]% Proj4 p4.dat
I am a Circle
-------------
Center : ( 3, 4 )
Radius : 2.6500
Area : 22.0618
Circumference: 16.6504
I am a Rectangle
----------------
Upper Left: ( 1, 7 ) UpperRight: ( 4, 7 )
Lower Left: ( 1, 2 ) LowerRight: ( 4, 2 )
Length : 3.0000
Width : 5.0000
Area : 15.0000
Perimeter : 16.0000
I am a Circle
-------------
Circle with radius -42.0000 is ill-formed
I am a Cylinder
---------------
Center : ( 3, 4 )
Radius : 4.7000
Area : 69.3977
Circumference: 29.5309
Volume : 249.8318
I am a Ring
-----------
Inner Circle
------------
Center : ( 2, 3 )
Radius : 2.7000
Area : 22.9022
Circumference: 16.9646
Outer Circle
------------
Center : ( 2, 3 )
Radius : 5.4000
Area : 91.6088
Circumference: 33.9292
Ring Area : 68.7066
I am a Sphere
-------------
Center : ( 4, 5 )
Radius : 2.6500
Area : 22.0618
Circumference: 16.6504
Volume : 77.9517
Surface Area : 88.2473
linux1[6]%
Hints, Suggestions and Free advice
- Mr. Frey's public directory for this project is
/afs/umbc.edu/users/d/e/dennis/pub/CMSC202/proj4
- Use incremental development
- Implement the Circle and Rectangle classes first. Write test program to
exercise their methods.
- Write main( ) and DrawShapes( ) and make them work
for Circles and Rectangles.
- Implement the Cyclinder class. Write a test program to exercise all the methods.
Then add Cylinders to main( )
- Implement the Ring class. Write a test program to exercise all its methods.
Then add Rings to main
- Add exceptions to your code. Keep the exception classes a simple as possible.
- Use a simple approach to reading the file. Using getline( ) is NOT recommended. A simple approach also makes EOF detection easier.
- Review the makefile for project 1 to see how to reference .H files in Mr. Frey's
public directory.
- Visit the discussion board
- To be sure your class' destructors are being called, temporarily put an
output statement in each one. Be sure to remove this output statement before
submitting your project.
- Use 3.14159 for the value of PI so your answers will match those
- The area of a circle = PI * radius2. It's not necessary to use
the pow( ) function.
- The circumference of a circle = 2 * PI * radius
- The volume of a cylinder = area of base * height
- The volume of a sphere is 4/3 * PI * radius3
Note that 4 / 3 is NOT the same as 4.0 / 3.0.... which should you use?
- The surface area of a sphere is 4 * PI * radius2
Project Design Assignment
Your project design document
for project 4 must be named design4.txt.
Be sure to read the design specification
carefully.
Submit your design in the usual way.
submit cs202 Proj4 design4.txt
Project Make File
You are required to submit a make file with this project.
The grader should simply need to type "make Proj4" and your project should compile
and link to an executable called Proj4. The grader should also have the ability
to do a "make clean" and "make cleanest."
Hint: Start with the makefile from project 1 and modify it as necessary.
See the
make tutorial for more help on make and makefiles.
Project Grading
The grade for this project will be broken down as follows. A more detailed
breakdown will be provided in the grade form you recieve
with your project grade.
This list should not be considered comprehensive, but rather a suggested list
of things you should consider before turning in your project.
85% - Correctness -- 85%
- Have you correctly used inheritance to define your classes?
- Have you properly reused code from the base class?
- Are all appropriate member functions "virtual"?
- Are all appropriate member functions "const"?
- Are all return values being returned in the appropriate way (by value, by reference,
by const reference)?
- Are all function parameters being passed into the function in the appropriate
way (by value, by reference, by const reference)?
- Does your output meet all output requirements?
- Are all calculated values correct?
- Have you properly implemented DrawShapes( )?
- Do all appropriate functions have the proper PreConditions? If so, are all
PreConditions handled?
- Are you throwing exceptions wherever required?
- Are all exceptions being caught and handled properly? I.e. being thrown
by the appropriate methods, caught by the caller and dealt with appropriately?
15% - Coding Standards
Your code adheres to the
CMSC 202 coding standards as discussed
and reviewed in class.
Project Submission
You should submit the following files.
- Shape.C -- the implementation of the Shape class
- Circle.C -- the implementation of the Circle class and its associated
exception class
- Rectangle.C -- the implementation of the Rectangle class and its associated
exception class
- Point.H and Point.C -- the definition and implementation of your Point class
- Cylinder.H and Cylinder.C -- the definition and implementation of your Cylinder class
and its associated exception class(es)
- Ring.H and Ring.C -- the definition and implementation of your Ring class
and its associated exception class(es)
- Sphere.H and Sphere.C -- the definition and implementation of your Sphere class
and its associated exception class(es)
- Proj4.C -- the main project file
- Your makefile
DO NOT SUBMITShape.H, Circle.H or Rectangle.H
Submit as follows:
submit cs202 Proj4
A complete guide to
submit tools is available on the course website.
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.