Polymorphism and Virtual Functions - SUNY

advertisement
CSE230 - C++ Notes 6
Polymorphism and Virtual Functions
Polymorphism
•It is possible to design and implement systems that are more easily
______________.
•Programs can be written to generically process – as base-class objects –
objects of all existing classes in a hierarchy.
•Classes that do not exist during program development can be added with
little or no modification to the generic part of the program – as long as those
classes are part of the hierarchy that is being processed generically.
•The only part of the program that will need modification are those parts that
require direct knowledge of the particular class that is added to the
hierarchy.
Polymorphism (cont’d)
•One means of dealing with objects of different types is to use a _________
statement.
•For example, in a hierarchy of shapes in which each shape specifies its type
as a data member, a _________ structure could determine which print
function to call based on the type of the particular object.
•Polymorphism and _________ functions can eliminate the need for switch
logic. It also avoids errors typically associated with equivalent switch logic
and facilitates testing, debugging and program maintenance.
•Suppose a set of shape classes such as Circle, Triangle, Square, etc.
are all derived from base class Shape and each class includes a separate
draw function.
Virtual Functions
•To draw any shape, we could simply call function draw of base class Shape
and let the program determine ____________ which derived class draw
function to use.
•To enable this kind behavior, draw must be declared in the base class (i.e.
Shape) as a virtual function and then each derived class overrides draw
to draw the appropriate shape.
•Following may appear in Shape:
virtual void draw() const;
•Once a function is declared virtual, it remains virtual all the way down
the inheritance hierarchy from that point even if it is not declared ________
when a class overrides it. However, explicit declaration promotes clarity.
1
Abstract and Concrete Classes
•A class is made abstract by declaring one or more of its _________
functions to be _______.
•No objects of an abstract base class can be instantiated.
•A ______ virtual function is one with an initializer of =NULL (or =0) in its
declaration as in:
virtual void draw() const = NULL; // =0
•If no definition is supplied in a derived class for a pure virtual function,
then the function remains to be pure. Consequently, the derived class is also
an abstract class.
#ifndef SHAPE_H
#define SHAPE_H
// abstract definition for Shape
class Shape {public:
// impure virtual functions
virtual double area() const { return 0.0; }
virtual double volume() const { return 0.0; }
// pure virtual functions overridden in each of the derived classes
virtual void printShapeName() const = _________; // = 0
virtual void print() const = ________;
// = 0
// non–virtual functions/data may be defined, but they are not needed in this class
}; // end class Shape
#endif
#ifndef POINT_H
#define POINT_H
#include <iostream>
using std::cout;
#include "shape.h"
class Point : public Shape {
public:
Point( int = 0, int = 0 ); // default constructor
void setPoint( int, int );
int getX() const { return x; }
int getY() const { return y; }
virtual void printShapeName() const { cout << "Point: "; }
virtual void print() const;
// __________ and __________ of a point are both 0.0 and they are inherited from Shape
private:
int x, y; // x and y coordinates of Point
}; // end class Point
#endif
#include "point.h“
Point::Point( int a, int b ) { setPoint( a, b ); }
void Point::setPoint( int a, int b )
{
x = a;
y = b;
} // end function setPoint
void Point::print() const
{ cout << '[' << x << ", " << y << ']'; }
2
#ifndef CIRCLE_H
#define CIRCLE_H
#include "point.h"
class Circle : public _________ {
public:
// default constructor
Circle( double r = 0.0, int x = 0, int y = 0 );
void setRadius( double );
double getRadius() const;
____________ double area() const;
virtual void printShapeName() const { cout << "Circle: "; }
virtual void print() const;
private:
double radius; // radius of Circle
}; // end class Circle
#endif
#include <iostream>
using std::cout;
#include "circle.h"
Circle::Circle( double r, int a, int b ) : Point( a, b ) // call base-class constructor
{ setRadius( r ); }
void Circle::setRadius( double r ) { radius = r > 0 ? r : 0; }
double Circle::getRadius() const { return radius; }
double Circle::area() const { return 3.14159 * radius * radius; }
void Circle::print() const
{
Point::print();
cout << "; Radius = " << radius;
} // end function print
#ifndef CYLINDER_H
#define CYLINDER_H
#include "circle.h"
class Cylinder : public ___________ {
public:
// default constructor
Cylinder( double h = 0.0, double r = 0.0, int x = 0, int y = 0 );
void setHeight( double );
double getHeight();
virtual double area() const;
______________ double volume() const;
virtual void printShapeName() const {cout << "Cylinder: ";}
virtual void print() const;
private:
double height; // height of Cylinder
}; // end class Cylinder
#endif
#include <iostream>
using std::cout;
#include "cylinder.h"
Cylinder::Cylinder( double h, double r, int x, int y ):Circle( r, x, y)//call base-class constructor
{ setHeight( h ); }
double Cylinder::getHeight() { return height; }
void Cylinder::setHeight( double h ) { height = h > 0 ? h : 0; }
double Cylinder::area() const
{
// surface area of Cylinder
return 2 * Circle::area() + 2 * 3.14159 * getRadius() * height;
} // end function area
double Cylinder::volume() const { return Circle::area() * height; }
3
void Cylinder::print() const
{
Circle::print();
cout << "; Height = " << height;
} // end function print
#include <iostream>
#include <iomanip>
using namespace std;
#include "shape.h"
#include "point.h"
#include "circle.h"
#include "cylinder.h“
// Make virtual function calls off a base-class pointer using dynamic binding.
void virtualViaPointer( const __________ *baseClassPtr )
{
baseClassPtr->printShapeName();
baseClassPtr->print();
cout<<"\nArea="<<baseClassPtr->area()<<"\nVolume="<< baseClassPtr->volume()<<"\n";
} // end function virtualViaPointer
// Make virtual function calls off a base-class reference using dynamic binding.
void virtualViaReference( const _________ &baseClassRef )
{
baseClassRef.printShapeName();
baseClassRef.print();
cout<<"\nArea="<< baseClassRef.area()<<"\nVolume="<< baseClassRef.volume()<<"\n";
} // end function virtualViaReference
int main()
{ cout << setiosflags( ios::fixed | ios::showpoint ) << setprecision( 2 );
Point point( 7, 11 );
// create a Point
Circle circle( 3.5, 22, 8 );
// create a Circle
Cylinder cylinder( 10, 3.3, 10, 10 ); // create a Cylinder
point.printShapeName();
// ________ binding
point.print();
// static binding
circle.printShapeName();
// static binding
circle.print();
// static binding
cylinder.printShapeName(); // static binding
cylinder.print();
// ________ binding
___________ *arrayOfShapes[ 3 ];
// array of base-class pointers
arrayOfShapes[ 0 ] = &point;
// aim arrayOfShapes[0] at derived-class Point object
arrayOfShapes[ 1 ] = &circle;
// aim arrayOfShapes[1] at derived-class Circle object
arrayOfShapes[ 2 ] = &cylinder; // aim arrayOfShapes[2] at derived-class Cylinder object
cout << "Virtual function calls made off " << "base-class pointers\n";
for ( int i = 0; i < 3; i++ ) // Loop through arrayOfShapes and call virtualViaPointer
virtualViaPointer( arrayOfShapes[ i ] );
cout << "Virtual function calls made off " << "base-class references\n";
for ( int j = 0; j < 3; j++ ) // Loop through arrayOfShapes and call virtualViaReference
virtualViaReference( *arrayOfShapes[ j ] );
return 0; } // end function main
4
Download