Title: More on inheritance Abstract classes Inheritance of constructorsdestructors Types of inheritance
1More on inheritanceAbstract classesInheritance
of constructors/destructorsTypes of inheritance
2Inheritance
Inheritance - mechanism of deriving new classes
from old ones. The keywords public, private, and
protected are used as visibility modifiers for
class members.
The keyword virtual is a function specifier that
provides a mechanism to dynamically select at
runtime the appropriate member function from
among base and derived class functions (polymorphi
smmany forms ). There are two types of virtual
functions virtual double area() // normal
virtual virtual double area() 0 // pure virtual
3Abstract Base Classes
A pure virtual function is one whose body is
undefined. virtual void printName() 0 A pure
virtual function is used to defer the
implementation decision of the function. A class
that has at least one pure virtual function is
called an abstract class (normal classes are
sometimes called concrete classes). Abstraction
is just a design mechanism - a way of
deferring design decisions.
4Abstract and concrete classes
- An abstract class is any class with one or more
pure virtual functions - it cannot be
instantiated - A class that can be instantiated is called a
concrete class - Sub-classes of an abstract class will inherit the
pure virtual functions in the base class and be
abstract classes themselves - If you want to make a sub-class of an abstract
class into a concrete class, you must over-ride
the pure virtual function and provide a concrete
implementation
5Shape - virtual area()0
ThreeD - virtual volume()0
TwoD
Rectangle
Circle
Sphere
If you do not supply implementations (bodies)
for all the inherited pure virtual function then
this class will remain abstract and
un-instantiable.
6Abstract Base Classes
Typically the base class in a hierarchy of
classes is an abstract class. (It is only there
to help the designer start the hierarchy - an
abstract class might often contain some data
declarations and maybe some methods, but it is
never intended to actually be instantiated) An
abstract class cannot be used to declare objects
(cannot be instantiated). An abstract class can
be used to declare pointers that can access
objects derived from the abstract base class.
7Inheritance rules
- A derived class inherits everything from its base
class except - Its constructors
- Its destructors
- Its assignment operators
- Its friends
8Virtual - constructors and destructors Constructo
rs are always dynamic (dont need
virtual.) Destructors should be declared virtual
(if you delete a derived class through a base
pointer.) There can be significant problems if
you dont declare destructors virtual and you try
to delete through the base pointer. (The wrong
memory can be freed up if your classes use
malloc or new etc).
9Consider a time keeper class hierarchy
class TimeKeeper public TimeKeeper() cout
ltlt "Base ctor ltlt endl TimeKeeper() cout ltlt
"Base dtor" ltlt endl class AtomicClock
public TimeKeeper public AtomicClock()
cout ltlt "AT ctor"ltltendl AtomicClock() cout
ltlt "AT dtor"ltltendl class WaterClock
public TimeKeeper class WristWatch
public TimeKeeper
10 and a piece of code that dynamically allocates
an object of some class derived from
TimeKeeper // Get option from user input at run
time TimeKeeper ptk if (option1) ptk
new AtomicClock() else if (option2) ptk
new WaterClock() else if (option3) ptk new
WristWatch() delete ptk
What destructors are called?
11Virtual Destructors
- Deleting an object via its base class pointer
will only call the base class destructor. - We want to destroy the entire object, ie call the
derived class destructor, then the base class
destructor - How?
12Make the base class destructor virtual class
TimeKeeper public TimeKeeper() cout ltlt
"Base ctor"ltltendl virtual TimeKeeper() cout
ltlt "Base dtor" ltlt endl Now the destructors
of the base and derived classes are called in the
right order This becomes very important if
memory allocations are done by these classes.
13When to use Virtual Destruction
- Even if your objects dont have any memory
cleanup to do and therefore dont need
anything other than the default destructor, it is
still important to have virtual destructors
- When storage is freed up (or deleted) the
address and size of the block of storage is
needed before it can be returned to the heap.
The destructor normally supplies this to the
operating system. Things can crash if this is
not properly passed.
14When?
- Generally it is safest always to use a virtual
destructor - however - class bit public char c
- Is very tiny - never designed to inherit from this
- In a case like this putting a virtual destructor
in the class will add four extra bytes - ie
going from one to five bytes - not really what
is wanted for something you might want to declare
a lot of.
15Base classes as parameter arguments
- Given a base class and a number of sub-classes
(and sub-subclasses), consider this function
definition - void doSomethingWithIt(BaseClass b)
- Any object of any sub-class of base class can be
passed through - in the same way that base class
pointers can point to any subclass - Example suppose we had developed a sophisticated
algorithm that we want to apply to any
mathematical function
16Simple example an algorithm to find the minimum
value of any given function of one variable that
may be declared as double myfunction(double x)
void findMinimum( )
What goes in here?
We could use a pointer-to-function and pass the
pointer as a parameter argument Void
findMinimum(double ()(double) A better way is
to pass through function objects
17class MathematicalFunction public virtual
double operator() (double x) 0 void
findMinimum(MathematicalFunction fun) //
Implement algorithm here class
MySpecialFunction public MathematicalFunction
// Provide a concrete implementation of ()
You can apply findMinimum to any object of any
subclass of MathematicalFunction
18 MySpecialFunction f findMinimum(f)
f is a function object or functor
See lecture demo functor.cpp See also C FAQ
Lite for discussion on functionoids
19Polymorphic Function Call
- Consider also a member function for the Shape
class - virtual void draw() 0
- And a utility standalone function that places any
shape on the screen - void placeShape(Shape s)
- // decide how to place the shape on the
screen, then invoke the draw method - s -gt draw()
-
- The placeShape function sends a message (function
call) to the whichever shape object is pointed
to, the correct draw method is then selected
polymorphically.
20Inheritance of friends
Friends of base classes are not friends of
subclasses class Base public friend
friendly_function() Class Derived public
Base private
The friends of Base do not have access to private
or protected members in Derived
21Public, protected, and private inheritance
When deriving a class Derived from another class
Base then
Base
Derived
22Summary A pure virtual function is a function
whose body is undefined. A class having a pure
virtual member function is an abstract class. An
abstract base class defines the interface for its
derived classes but cannot itself be used to
declare objects. Polymorphism - the ability for
objects of different classes related by
inheritance to respond differently to the same
message (function call). Constructors,
destructors, assignment, and friends are not
inherited. Virtual destructors should be used in
base classes. We can use more elaborate
combinations of the access modifiers when
deriving classes from base classes.