lab
EECS 280 Lab 05: Inheritance and Subtype Polymorphism
Lab Due Sunday, October 18, 2020, 8:00 pm
Direct autograder link
In this lab, we will use a set of Abstract Data Types (ADTs) to write an ASCII art drawing program. We’ve provided a Canvas ADT that manages an image (i.e. a grid of “pixels”) and you will finish a hierarchy that represents the shapes that may be drawn. Additionally, we’ve prepared an Exam Prep that reviews similar topics. Finally, we’ve included some optional exam-style practice problems to study for the exam.
You may work alone or with a partner. Please see the syllabus for partnership rules.
Submit the code files below on the autograder. We encourage you to complete the lab Exam Prep, but it is not turned in for credit.
Files to submit
shapes.hshapes.cpp
Completion Criteria/Checklist:
To pass this lab, you must finish tasks 1 and 2.
-
(Task 1) Declare a derived class
CirclefromEllipseinshapes.hand implement the necessary functions inside ofshapes.cpp. Don’t override any member functions. -
(Task 2) Declare a derived class
RectanglefromShapeinshapes.hand implement the necessary functions inside ofshapes.cpp. Override bothareaanddraw.
Lab Exercises
The Files
$ wget eecs280staff.github.io/lab/lab05/starter-files.tar.gz
$ tar -xvzf starter-files.tar.gz
Here’s a summary of this lab’s files. You will turn in the bolded ones.
| File | Description |
|---|---|
Canvas.h |
Declaration of the Canvas ADT. |
Canvas.cpp |
Implementations of the member functions for Canvas. |
lab05.cpp |
Includes the main function, which draws some shapes. |
shapes.h |
Declaration of the Shape class and its derived classes. |
shapes.cpp |
Implementations of Shape and its derived classes. |
Testing Code
The main function in lab05.cpp creates an Ellipse, a Circle,
and a Rectangle and stores pointers to them in a shapes array to
draw them to a Canvas. Some parts are commented out to ensure the
starter code compiles. You may comment things in/out as you work on
different tasks.
The starter code should compile successfully without any modifications, so make sure you are able to compile and run it with the following commands. The code may be missing some pieces, contain some bugs, or crash when you run it, but you’ll fix each throughout the course of the lab.
$ g++ -Wall -Werror -g -pedantic --std=c++11 Canvas.cpp shapes.cpp lab05.cpp -o lab05.exe
$ ./lab05.exe
Introduction
You should first familiarize yourself with the ADTs we will use in
this lab. They are described briefly below and in the comments in
Canvas.h and shapes.h. As with any good ADT, you shouldn’t need to
look at the implementations to know what they do and how to use them.
Canvas
A Canvas represents a 2D image and supports these operations.
-
void set_pixel(int x, int y, bool value)Sets a pixel in the
Canvasto ON (true) or OFF (false). Initially, all pixels are set to OFF. -
void print() constPrints out the image in the
Canvasto the terminal.
Shape
A Shape is an abstract base class that represents a geometric shape.
It declares the two pure virtual functions area and draw, which
means that each derived class must implement both functions according
to the shape they represent. Furthermore, since they are virtual, when
we use a pointer to Shape, the appropriate implementation for that
shape will be used.
Note: Since the functions are pure virtual, we cannot instantiate
a Shape object. However, we will be able to instantiate derived
classes of Shape that provide implementations of these functions.
Ellipse

An Ellipse is an example of a derived type, which inherits from
Shape. It is defined by x and y radii as shown in the picture. You
can see that both area and draw are overridden from Shape, to
work for an Ellipse.
Drawing on a Canvas
In order to draw the Ellipse, we check every pixel in the Canvas
and we turn it ON if it is contained inside the shape. To determine
whether a pixel is inside, we use the equation for an ellipse based on
its x/y position and radii (don’t worry, you don’t need to know this
formula, since the shapes you’re asked to implement are simpler).
Note: In the draw implementation, why are we able to access the
x_rad and y_rad member variables directly, but we need to use the
getters for x_pos and y_pos?
Task 1 - Circle
Start by writing Circle. Here are some things to consider:
- Separate your code into
shapes.handshapes.cppappropriately. Circleshould be derived fromEllipse(which itself is derived fromShape).- The constructor should take in a single
doublefor itsradius. - Remember that a
Circleis just a special case of anEllipse.
Note: You shouldn’t need to create any private variables or override any functions.
In order to try your new shape, start by uncommenting the relevant
code inside lab05.cpp. Now, you will need to increase SIZE and add
the new shape to the shapes array.
Task 2 - Rectangle
Next we will write Rectangle. Again, here are some things to
consider:
- Separate your code into
shapes.handshapes.cppappropriately. Rectangleshould be derived directly fromShape.- The constructor should take in two
doubles for itswidthandheight, respectively. - You need to declare additional member variables to store the
widthandheight. - You need to override both
areaanddraw, because they are pure virtual inShape. - For
draw, follow the same structure used inEllipse: check every pixel in theCanvasand turn it ON if it is contained inside the shape. - Remember that a rectangle at \(\left( x_{pos}, y_{pos} \right)\) contains the point \(\left( x, y \right)\) if and only if \(\left| x - x_{pos} \right| \leq \frac{width}{2}\) and \(\left| y - y_{pos} \right| \leq \frac{height}{2}\)
Note: You may find the abs function helpful to obtain the
absolute value of a number.
Now uncomment the relevant code in lab05.cpp and add rect to the
shapes array. Since the array is now holding shapes other than
Ellipses you will also need to change the type of the array to hold
Shape pointers.
Submit
Submit the required files to the autograder.