Inheritance and Polymorphism C++ program For this project, you will create a ser
ID: 3766741 • Letter: I
Question
Inheritance and Polymorphism C++ program
For this project, you will create a series of classes to represent some simple geometric shapes and a small program to test your classes.
class Shape
Shape is an abstract base class.
Data Members
A Shape has the following private data member:
a color, which is of type string,
Methods
The Shape class should have the following public methods:
a constructor that takes a const string& argument and uses it to initialize the shape's color. Since the Shape class is abstract, this constructor will only be invoked by a derived-class constructor.
a virtual destructor. The method body for this destructor can be empty, since it does not need to delete any dynamic storage. If you don't have a virtual destructor for an abstract base class, the compiler may produce a warning message.
a virtual method called print() that takes no arguments and returns nothing. The method should print the color.
a pure virtual method called get_area() that takes no arguments and returns a double. Since it is pure virtual (or abstract), this method has no definition, only a prototype. It must be defined in any concrete class derived from Shape.
class Circle
Circle is derived from Shape using public inheritance.
Data Members
A Circle has the following private data member:
a radius, which is of type int,
Methods
The Circle class should have the following methods:
a constructor that takes a string to initialize the circle's color and an int to initiallize the circle's radius. The color string should be passed to theShape constructor.
an overridden version of print() that takes no arguments and returns nothing. The method should call the base class print() method to print the color, then print the word "circle" followed by the circle's radius and area, e.g.:
an overridden version of get_area() that takes no arguments and returns a double. This method should compute and return the circle's area based on its radius.
class Rectangle
Rectangle is derived from Shape using public inheritance.
Data Members
A Rectangle has the following private data member:
a height, which is of type int,
a width, which is of type int,
Methods
The Rectangle class should have the following methods:
a constructor that takes a string to initialize the circle's color and two ints to initialize the rectangle's height and width. The color string should be passed to the Shape constructor.
an overridden version of print() that takes no arguments and returns nothing. The method should call the base class print() method to print the color, then print the word "rectangle" followed by the rectangle's height, width, and area, e.g.:
an overridden version of get_area() that takes no arguments and returns a double. This method should compute and return the rectangle's area based on its height and width.
class Triangle
Triangle is derived from Shape using public inheritance.
Data Members
A Triangle has the following private data member:
a height, which is of type int,
a base, which is of type int,
Methods
The Triangle class should have the following methods:
a constructor that takes a string to initialize the triangle's color and two ints to initialize the triangle's height and base. The color string should be passed to the Shape constructor.
an overridden version of print() that takes no arguments and returns nothing. The method should call the base class print() method to print the color, then print the word "triangle" followed by the triangle's height, base, and area, e.g.:
an overridden version of get_area() that takes no arguments and returns a double. This method should compute and return the rectangle's area based on its height and width.
Main Program
Write a test program that creates either an array or an STL vector of pointers to Shape objects.
Dynamically create some Circles, Rectangles, and Triangles (at least two of each). After creating each object, add it to the array or vector.
Loop through the array or vector of Shape pointers and call the print() method for each of them.
Loop through the array or vector of Shape pointers again and call the print() method for each of the Triangle objects in the array or vector.
Loop through the list of Shape pointers one more time and delete each object.
Output from this program should look something like this:
Explanation / Answer
#include <iostream>
using namespace std;
/* A complete demonstration - base class, derived classes (and derived class
from derived class too), with an array of various objects of the similar types
and code to access those objects */
class Shape {
public:
float width;
float height;
// bool cached; Later ;-)
virtual float getarea() {} ; };
class Circle: public Shape {
public:
Circle(float radius);
float getarea() ; };
class Rectangle: public Shape {
public:
Rectangle(float width, float height);
float getarea() ; };
class Square: public Rectangle {
public:
Square(float size); };
Square::Square (float size) : Rectangle(size, size) { }
Rectangle::Rectangle(float width, float height) {
this->width = width; this->height = height; }
Circle::Circle (float radius) {
this->width = this->height = radius * 2.0; }
float Circle::getarea() { return width * width * 3.14159265 / 4.0; }
float Rectangle::getarea() { return width * height ; }
int main (int argc, char **argv) {
Shape * papers[5];
Circle michael(15.0);
Rectangle andrew(34.0,2.0);
Circle ann(2.3);
Square tim(3.33);
Rectangle jonathan(5.61,7.92);
papers[0] = &michael; papers[1] = &andrew; papers[2] = &ann;
papers[3] = &tim; papers[4] = &jonathan;
for (int k=0; k<5; k++) {
cout << "Area is " << papers[k]->getarea() << endl;
}
}
/* Sample Output
munchkin:c5 grahamellis$ ./shapes_01
Area is 706.858
Area is 68
Area is 16.619
Area is 11.0889
Area is 44.4312
munchkin:c5 grahamellis$
*/
The word polymorphism means having many forms. Typically, polymorphism occurs when there is a hierarchy of classes and they are related by inheritance.
C++ polymorphism means that a call to a member function will cause a different function to be executed depending on the type of object that invokes the function.
Consider the following example where a base class has been derived by other two classes:
#include <iostream>
using namespace std;
class Shape {
protected:
int width, height;
public:
Shape( int a=0, int b=0)
{
width = a;
height = b;
}
int area()
{
cout << "Parent class area :" <<endl;
return 0;
}
};
class Rectangle: public Shape{
public:
Rectangle( int a=0, int b=0):Shape(a, b) { }
int area ()
{
cout << "Rectangle class area :" <<endl;
return (width * height);
}
};
class Triangle: public Shape{
public:
Triangle( int a=0, int b=0):Shape(a, b) { }
int area ()
{
cout << "Triangle class area :" <<endl;
return (width * height / 2);
}
};
// Main function for the program
int main( )
{
Shape *shape;
Rectangle rec(10,7);
Triangle tri(10,5);
// store the address of Rectangle
shape = &rec;
// call rectangle area.
shape->area();
// store the address of Triangle
shape = &tri;
// call triangle area.
shape->area();
return 0;
}
When the above code is compiled and executed, it produces the following result:
Parent class area
Parent class area
The reason for the incorrect output is that the call of the function area() is being set once by the compiler as the version defined in the base class. This is called static resolution of the function call, or static linkage - the function call is fixed before the program is executed. This is also sometimes called early binding because the area() function is set during the compilation of the program.
But now, let's make a slight modification in our program and precede the declaration of area() in the Shape class with the keyword virtual so that it looks like this:
class Shape {
protected:
int width, height;
public:
Shape( int a=0, int b=0)
{
width = a;
height = b;
}
virtual int area()
{
cout << "Parent class area :" <<endl;
return 0;
}
};
After this slight modification, when the previous example code is compiled and executed, it produces the following result:
Rectangle class area
Triangle class area
This time, the compiler looks at the contents of the pointer instead of it's type. Hence, since addresses of objects of tri and rec classes are stored in *shape the respective area() function is called.
As you can see, each of the child classes has a separate implementation for the function area(). This is how polymorphism is generally used. You have different classes with a function of the same name, and even the same parameters, but with different implementations.
Virtual Function:
A virtual function is a function in a base class that is declared using the keyword virtual. Defining in a base class a virtual function, with another version in a derived class, signals to the compiler that we don't want static linkage for this function.
What we do want is the selection of the function to be called at any given point in the program to be based on the kind of object for which it is called. This sort of operation is referred to as dynamic linkage, or late binding.
Pure Virtual Functions:
It's possible that you'd want to include a virtual function in a base class so that it may be redefined in a derived class to suit the objects of that class, but that there is no meaningful definition you could give for the function in the base class.
We can change the virtual function area() in the base class to the following:
class Shape {
protected:
int width, height;
public:
Shape( int a=0, int b=0)
{
width = a;
height = b;
}
// pure virtual function
virtual int area() = 0;
};
The = 0 tells the compiler that the function has no body and above virtual function will be called pure virtual function.