Lab CPP 08 Inheritance
Lab CPP 08 Inheritance
IAP 2021
Michael Benjamin, [email protected]
Department of Mechanical Engineering
Computer Science and Artificial Intelligence Laboratory (CSAIL)
MIT, Cambridge MA 02139
3 Polymorphism 4
3.1 Exercise 3: Using Polymorphism in our Shapes Example . . . . . . . . . . . . . . . . . . . . . 5
3.2 Exercise 4: Implementing Virtual Functions in our Shapes Example . . . . . . . . . . . . . . 5
3.3 Exercise 5: One Final Improvement to our Shapes Example . . . . . . . . . . . . . . . . . . . 7
4 Solutions to Exercises 8
4.1 Solution to Exercise 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
4.2 Solution to Exercise 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
4.3 Solution to Exercise 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
4.4 Solution to Exercise 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
4.5 Solution to Exercise 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
4.6 A Makefile for All Exercises in this Lab . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
1
2
1 Lab Eight Overview and Objectives
In this lab C++ class inheritance (sub-classing) is explored. This is one of the key capabilities in
object-oriented program and is a prime distinction between C and C++. In MOOS-IvP it is also a
key concept since all MOOS apps inherit from a MOOSApp superclass and all IvP Helm behaviors
inherit from a IvPBehavior superclass. In this lab we will build a couple simple subclasses of the
SegList class used previously in Lab 05.
In this lab the following topics are covered.
• C++ Subclasses
• Polymorphism
• Encapsulation
• Function Overloading
• Virtual Functions
After you’ve read the above link(s), you should be ready for a couple short exercises.
3
After instantiating and populating two instances, with the above vertices, just output the result of
getSpec() to the terminal.
Call your files Triangle.cpp/h, Square.cpp/h and shapes v1.cpp and build it to the executable
shapes v1. When your program runs it should be invocable from the command line with:
$ ./shapes_v1
Triangle: type=triangle,x=0,y=0,x=10,y=0,x=5,y=5
Square: type=square,x=0,y=0,x=10,y=0,x=10,y=10,x=0,y=10
Building shapes v1: From the previous lab on Build Systems and Makefiles, you should be
able to make a simple Makefile for this exercise. If you’d like to peek ahead at a Makefile for all five
exercises in this lab, see Section 4.6.
$ ./shapes_v2
Triangle: type=triangle,x=0,y=0,x=10,y=0,x=5,y=5
Perimeter: 24.1421
Square: type=square,x=0,y=0,x=10,y=0,x=10,y=10,x=0,y=10
Perimeter: 40
3 Polymorphism
The term polymorphism refers to the ability to have several functions, with the same name, do different
things depending on which class is invoking the function. A simple example of polymorphism:
1 + 2 // Integer addition
1.1 + 2.2 // Floating point addition
"1" + "2" // String concatenation
4
Another example is when different classes have the same function defined, even with same semantic
meaning, but behavior differently depending on the class. For example, in our next exercise we define
the getArea() function on both the Triangle and Square classes, but the function is implemented
differently to reflect the different way that area is calculated. Before proceeding to this exercise,
have a read of:
• http://www.cplusplus.com/doc/tutorial/polymorphism
Note that they are const functions since they don’t alter the state of the object, only report on
existing properties. After you have implemented these utility functions, implementing the getArea()
function in both the Triangle and Square classes should be much simpler.
Implement your new getArea() functions on copies of the existing classes, now called TriangleV3.cpp/h
and SquareV3.cpp/h. Implement your getMin*() utility functions on a copy of the existing superclass,
now called SegListV3.cpp/h. Your new main() function should be in shapes v3.cpp, and will only
be modified to show the newly calculated area on the same example shapes as the first exercises.
When your program runs it should be invocable from the command line with:
$ ./shapes_v3
Triangle: type=triangle,x=0,y=0,x=10,y=0,x=5,y=5
Area: 25
Square: type=square,x=0,y=0,x=10,y=0,x=10,y=10,x=0,y=10
Area: 100
Building shapes v3: From the previous lab on Build Systems and Makefiles, you should be able
to make a simple Makefile for this exercise. If you’d like to peek ahead at a Makefile for all five
exercises in this lab, see Section 4.6.
5
generic manner since they both have the same superclass. For example, we should be able to have a
container, such as a vector or list, of such instances and add up all their areas, not caring whether
any of the instances is a Triangle or Square. In these cases the containers will contain pointers to
the baseclass. For example:
• vector<SegList*> my shapes;
In our example so far, it is possible to create the above type of container, but if one were to try to
invoke the getArea() function on any of the instances, it would be disallowed since this function is
not defined on the SegList base class. To see this, consider the below code snippet. This snippet
assumes a valid Triangle and Square instance have been created as with all our prior exercises.
In this snippet two base-class pointers are created, shape1 and shape2, pointing to the Triangle and
Square instance respectively. This is fine, but if you tried to do this the compiler would complain
about the following two lines:
This is because the getArea() function is not defined (yet) on the base class. To overcome this,
we can define the getArea() function as a virtual function at the base class level. A discussion on
virtual functions can be found a the following URLs:
• http://www.cplusplus.com/doc/tutorial/polymorphism
Your job in this exercise is to add the getArea() function as a virtual function in the super-
class. This modified superclass will be called SegListV4.cpp/h. Also create TriangleV4.cpp/h and
SquareV4.cpp/h to use this new superclass. Confirm that the above snippet works in your new
shapes v4.cpp function. When your program runs it should be invocable from the command line
with:
$ ./shapes_v4
Triangle: x=0,y=0,x=10,y=0,x=5,y=5
Area: 25
Square: x=0,y=0,x=10,y=0,x=10,y=10,x=0,y=10
Area: 100
6
Building shapes v4: From the previous lab on Build Systems and Makefiles, you should be able
to make a simple Makefile for this exercise. If you’d like to peek ahead at a Makefile for all five
exercises in this lab, see Section 4.6.
Triangle: x=0,y=0,x=10,y=0,x=5,y=5
Square: x=0,y=0,x=10,y=0,x=10,y=10,x=0,y=10
Triangle: type=triangle,x=0,y=0,x=10,y=0,x=5,y=5
Square: type=square,x=0,y=0,x=10,y=0,x=10,y=10,x=0,y=10
Do you see the difference? Before addressing why this change occurred, and fixing it here in this
exercise, see if you can determine what caused the change before reading on....
Once we start regarding our shapes generically, as in the previous exercise, with pointers to the
base class, we need to be aware that a invocation to a function like SegList::getSpec() will invoke
exactly that function, not the Subclass::getSpec() function. Unless the base class function is
virtual. Try making the getSpec() function in the base class virtual, and notice that the output
reverts to again include the type information.
The solution to this exercise is in Section 4.5. It simply shows the one line change to SegListV4.h
to make the getSpec() function in the base class to be now virtual.
7
4 Solutions to Exercises
4.1 Solution to Exercise 1
*-----------------------------------------------------------------------*/
/* FILE: shapes_v1.cpp (Eighth C++ Lab Exercise 1) */
/* WGET: wget http://oceanai.mit.edu/cpplabs/shapes_v1.cpp */
/* RUN: shapes_v1 */
/*----------------------------------------------------------------------*/
int main()
{
Triangle triangle;
Vertex t_vertex1(0,0);
Vertex t_vertex2(10,0);
Vertex t_vertex3(5,5);
triangle.addVertex(t_vertex1);
triangle.addVertex(t_vertex2);
triangle.addVertex(t_vertex3);
Square square;
Vertex s_vertex1(0,0);
Vertex s_vertex2(10,0);
Vertex s_vertex3(10,10);
Vertex s_vertex4(0,10);
square.addVertex(s_vertex1);
square.addVertex(s_vertex2);
square.addVertex(s_vertex3);
square.addVertex(s_vertex4);
return(0);
}
8
/*----------------------------------------------------------------------*/
/* FILE: Triangle.h */
/* WGET: wget http://oceanai.mit.edu/cpplabs/Triangle.h */
/*----------------------------------------------------------------------*/
#ifndef TRIANGLE_HEADER
#define TRIANGLE_HEADER
#include "SegList.h"
std::string getSpec() const; // recall const just means that this function
}; // won’t alter the state of an instance.
#endif
/*----------------------------------------------------------------------*/
/* FILE: Triangle.cpp */
/* WGET: wget http://oceanai.mit.edu/cpplabs/Triangle.cpp */
/*----------------------------------------------------------------------*/
#include "Triangle.h"
//-----------------------------------------------------------------------
// Procedure: getSpec()
9
/*----------------------------------------------------------------------*/
/* FILE: Square.h */
/* WGET: wget http://oceanai.mit.edu/cpplabs/Square.h */
/*----------------------------------------------------------------------*/
#ifndef SQUARE_HEADER
#define SQUARE_HEADER
#include "SegList.h"
#endif
/*----------------------------------------------------------------------*/
/* FILE: Square.cpp */
/* WGET: wget http://oceanai.mit.edu/cpplabs/Square.cpp */
/*----------------------------------------------------------------------*/
#include "Square.h"
//-----------------------------------------------------------------------
// Procedure: getSpec()
10
4.2 Solution to Exercise 2
/*----------------------------------------------------------------------*/
/* FILE: shapes_v2.cpp (Eighth C++ Lab Exercise 2) */
/* WGET: wget http://oceanai.mit.edu/cpplabs/shapes_v2.cpp */
/* RUN: shapes_v2 */
/*----------------------------------------------------------------------*/
int main()
{
TriangleV2 triangle;
Vertex t_vertex1(0,0);
Vertex t_vertex2(10,0);
Vertex t_vertex3(5,5);
triangle.addVertex(t_vertex1);
triangle.addVertex(t_vertex2);
triangle.addVertex(t_vertex3);
SquareV2 square;
Vertex s_vertex1(0,0);
Vertex s_vertex2(10,0);
Vertex s_vertex3(10,10);
Vertex s_vertex4(0,10);
square.addVertex(s_vertex1);
square.addVertex(s_vertex2);
square.addVertex(s_vertex3);
square.addVertex(s_vertex4);
return(0);
11
/*----------------------------------------------------------------------*/
/* FILE: SegListV2.h */
/* WGET: wget http://oceanai.mit.edu/cpplabs/SegListV2.h */
/*----------------------------------------------------------------------*/
#ifndef SEGLIST_V2_HEADER
#define SEGLIST_V2_HEADER
#include <string>
#include <vector>
#include "Vertex.h"
class SegListV2 {
public:
SegListV2() {};
~SegListV2() {};
protected:
std::vector<Vertex> m_vertices;
};
#endif
12
/*----------------------------------------------------------------------*/
/* FILE: SegListV2.cpp */
/* WGET: wget http://oceanai.mit.edu/cpplabs/SegListV2.cpp */
/*----------------------------------------------------------------------*/
//-----------------------------------------------------------------------
// Procedure: getSpec
return(spec);
}
//-----------------------------------------------------------------------
// Procedure: getPerimeter
return(total);
}
13
/*----------------------------------------------------------------------*/
/* FILE: TriangleV2.h */
/* WGET: wget http://oceanai.mit.edu/cpplabs/TriangleV2.h */
/*----------------------------------------------------------------------*/
#ifndef TRIANGLE_V2_HEADER
#define TRIANGLE_V2_HEADER
#include "SegListV2.h"
#endif
/*----------------------------------------------------------------------*/
/* FILE: TriangleV2.cpp */
/* WGET: wget http://oceanai.mit.edu/cpplabs/Triangle.cpp */
/*----------------------------------------------------------------------*/
#include "TriangleV2.h"
//-----------------------------------------------------------------------
// Procedure: getSpec()
14
/*----------------------------------------------------------------------*/
/* FILE: SquareV2.h */
/* WGET: wget http://oceanai.mit.edu/cpplabs/SquareV2.h */
/*----------------------------------------------------------------------*/
#ifndef SQUARE_V2_HEADER
#define SQUARE_V2_HEADER
#include "SegListV2.h"
/*----------------------------------------------------------------------*/
/* FILE: SquareV2.cpp */
/* WGET: wget http://oceanai.mit.edu/cpplabs/TriangleV2.cpp */
/*----------------------------------------------------------------------*/
#include "SquareV2.h"
//-----------------------------------------------------------------------
// Procedure: getSpec()
15
4.3 Solution to Exercise 3
/*----------------------------------------------------------------------*/
/* FILE: shapes_v3.cpp (Eighth C++ Lab Exercise 3) */
/* WGET: wget http://oceanai.mit.edu/cpplabs/shapes_v3.cpp */
/* RUN: shapes_v3 */
/*----------------------------------------------------------------------*/
int main()
{
TriangleV3 triangle;
Vertex t_vertex1(0,0);
Vertex t_vertex2(10,0);
Vertex t_vertex3(5,5);
triangle.addVertex(t_vertex1);
triangle.addVertex(t_vertex2);
triangle.addVertex(t_vertex3);
SquareV3 square;
Vertex s_vertex1(0,0);
Vertex s_vertex2(10,0);
Vertex s_vertex3(10,10);
Vertex s_vertex4(0,10);
square.addVertex(s_vertex1);
square.addVertex(s_vertex2);
square.addVertex(s_vertex3);
square.addVertex(s_vertex4);
return(0);
}
16
/*----------------------------------------------------------------------*/
/* FILE: SegListV3.h */
/* WGET: wget http://oceanai.mit.edu/cpplabs/SegListV3.h */
/*----------------------------------------------------------------------*/
#ifndef SEGLIST_V3_HEADER
#define SEGLIST_V3_HEADER
#include <string>
#include <vector>
#include "Vertex.h"
class SegListV3 {
public:
SegListV3() {};
~SegListV3() {};
protected:
std::vector<Vertex> m_vertices;
};
#endif
17
/*----------------------------------------------------------------------*/
/* FILE: SegListV3.cpp */
/* WGET: wget http://oceanai.mit.edu/cpplabs/SegListV3.cpp */
/*----------------------------------------------------------------------*/
#include "SegListV3.h"
//-----------------------------------------------------------------------
// Procedure: getSpec
//-----------------------------------------------------------------------
// Procedure: getMinX()
//-----------------------------------------------------------------------
// Procedure: getMaxX()
18
//-----------------------------------------------------------------------
// Procedure: getMinY()
//-----------------------------------------------------------------------
// Procedure: getMaxY()
/*----------------------------------------------------------------------*/
/* FILE: TriangleV3.h */
/* WGET: wget http://oceanai.mit.edu/cpplabs/TriangleV3.h */
/*----------------------------------------------------------------------*/
#ifndef TRIANGLE_V3_HEADER
#define TRIANGLE_V3_HEADER
#include <string>
#include <vector>
#include "SegListV3.h"
#endif
19
/*----------------------------------------------------------------------*/
/* FILE: TriangleV3.cpp */
/* WGET: wget http://oceanai.mit.edu/cpplabs/TriangleV3.cpp */
/*----------------------------------------------------------------------*/
#include "TriangleV3.h"
//-----------------------------------------------------------------------
// Procedure: getSpec()
//-----------------------------------------------------------------------
// Procedure: getArea()
return(square_area / 2);
}
20
/*----------------------------------------------------------------------*/
/* FILE: SquareV3.h */
/* WGET: wget http://oceanai.mit.edu/cpplabs/SquareV3.h */
/*----------------------------------------------------------------------*/
#ifndef SQUARE_V3_HEADER
#define SQUARE_V3_HEADER
#include <string>
#include "SegListV3.h"
#endif
21
/*----------------------------------------------------------------------*/
/* FILE: SquareV3.cpp */
/* WGET: wget http://oceanai.mit.edu/cpplabs/SquareV3.cpp */
/*----------------------------------------------------------------------*/
#include "SquareV3.h"
//-----------------------------------------------------------------------
// Procedure: getSpec()
//-----------------------------------------------------------------------
// Procedure: getArea()
return(area);
}
22
4.4 Solution to Exercise 4
/*----------------------------------------------------------------------*/
/* FILE: shapes_v4.cpp (Eighth C++ Lab Exercise 4) */
/* WGET: wget http://oceanai.mit.edu/cpplabs/shapes_v4.cpp */
/* RUN: shapes_v4 */
/*----------------------------------------------------------------------*/
int main()
{
TriangleV4 triangle;
Vertex t_vertex1(0,0);
Vertex t_vertex2(10,0);
Vertex t_vertex3(5,5);
triangle.addVertex(t_vertex1);
triangle.addVertex(t_vertex2);
triangle.addVertex(t_vertex3);
SquareV4 square;
Vertex s_vertex1(0,0);
Vertex s_vertex2(10,0);
Vertex s_vertex3(10,10);
Vertex s_vertex4(0,10);
square.addVertex(s_vertex1);
square.addVertex(s_vertex2);
square.addVertex(s_vertex3);
square.addVertex(s_vertex4);
return(0);
}
23
/*----------------------------------------------------------------------*/
/* FILE: SegListV4.h */
/* WGET: wget http://oceanai.mit.edu/cpplabs/SegListV4.h */
/*----------------------------------------------------------------------*/
#ifndef SEGLIST_V4_HEADER
#define SEGLIST_V4_HEADER
#include <string>
#include <vector>
#include "Vertex.h"
class SegListV4 {
public:
SegListV4() {};
~SegListV4() {};
protected:
std::vector<Vertex> m_vertices;
};
#endif
24
/*----------------------------------------------------------------------*/
/* FILE: SegListV4.cpp */
/* WGET: wget http://oceanai.mit.edu/cpplabs/SegListV4.cpp */
/*----------------------------------------------------------------------*/
#include "SegListV4.h"
//-----------------------------------------------------------------------
// Procedure: getSpec
//-----------------------------------------------------------------------
// Procedure: getMinX()
//-----------------------------------------------------------------------
// Procedure: getMaxX()
25
//-----------------------------------------------------------------------
// Procedure: getMinY()
//-----------------------------------------------------------------------
// Procedure: getMaxY()
/*----------------------------------------------------------------------*/
/* FILE: TriangleV4.h */
/* WGET: wget http://oceanai.mit.edu/cpplabs/TriangleV4.h */
/*----------------------------------------------------------------------*/
#ifndef TRIANGLE_V4_HEADER
#define TRIANGLE_V4_HEADER
#include <string>
#include <vector>
#include "SegListV4.h"
#endif
26
/*----------------------------------------------------------------------*/
/* FILE: TriangleV4.cpp */
/* WGET: wget http://oceanai.mit.edu/cpplabs/TriangleV4.cpp */
/*----------------------------------------------------------------------*/
#include "TriangleV4.h"
//-----------------------------------------------------------------------
// Procedure: getSpec()
//-----------------------------------------------------------------------
// Procedure: getArea()
return(square_area / 2);
}
27
/*----------------------------------------------------------------------*/
/* FILE: SquareV4.h */
/* WGET: wget http://oceanai.mit.edu/cpplabs/SquareV4.h */
/*----------------------------------------------------------------------*/
#ifndef SQUARE_V4_HEADER
#define SQUARE_V4_HEADER
#include <string>
#include "SegListV4.h"
28
/*----------------------------------------------------------------------*/
/* FILE: SquareV4.cpp */
/* WGET: wget http://oceanai.mit.edu/cpplabs/SquareV4.cpp */
/*----------------------------------------------------------------------*/
#include "SquareV4.h"
//-----------------------------------------------------------------------
// Procedure: getSpec()
//-----------------------------------------------------------------------
// Procedure: getArea()
return(area);
}
29
4.5 Solution to Exercise 5
/*----------------------------------------------------------------------*/
/* FILE: SegListV4.h */
/* WGET: wget http://oceanai.mit.edu/cpplabs/SegListV4.h */
/*----------------------------------------------------------------------*/
#ifndef SEGLIST_V4_HEADER
#define SEGLIST_V4_HEADER
#include <string>
#include <vector>
#include "Vertex.h"
class SegListV4 {
public:
SegListV4() {};
~SegListV4() {};
protected:
std::vector<Vertex> m_vertices;
};
#endif
30
4.6 A Makefile for All Exercises in this Lab
#----------------------------------------------------------------------
# Builing a simple Triangle and Square subclass
v1_source = shapes_v1.cpp Triangle.cpp Square.cpp
v1_headers = Triangle.h Square.h
#----------------------------------------------------------------------
# Using an inherited function getPerimeter in the subclasses
v2_source = shapes_v2.cpp TriangleV2.cpp SquareV2.cpp SegListV2.cpp
v2_headers = TriangleV2.h SquareV2.h SegListV2.h
#----------------------------------------------------------------------
# Polymorphism: implementing an area() function in the subclasses
v3_source = shapes_v3.cpp TriangleV3.cpp SquareV3.cpp SegListV3.cpp
v3_headers = TriangleV3.h SquareV3.h SegListV3.h
#----------------------------------------------------------------------
# Virtual functions: making area() virtual, using base-class pointers
v4_source = shapes_v4.cpp TriangleV4.cpp SquareV4.cpp SegListV4.cpp
v4_headers = TriangleV4.h SquareV4.h SegListV4.h
#----------------------------------------------------------------------
clean:
rm -f shapes_v1 shapes_v2 shapes_v3 shapes_v4
31