UMBC CMSC202, Computer Science II, Fall 1998,
Sections 0101, 0102, 0103, 0104
Tuesday November 17, 1998
Assigned Reading: 10.1-10.6
Handouts (available on-line):
Programs from this lecture:
- Explained how virtual functions really work (we have a table
of function pointers for each derived class). Explained constructors
and destructors again, especially virtual destructors.
- We continue with the generic quicksort example from the previous
lecture. With some compilers, we can separate a template file into two
pieces: a header file and an implementation file. This is similar to the
situation with normal functions. The header file would contain templates
for function prototypes. The implementation file would contain the
templates for the function definitions. We do this for the generic
quicksort function: header file and
implementation file. This
arrangement works with the CC compiler, but not with the g++ compiler. The
CC compiler assumes that if you include a template header file called
"quicksort3.h" then the corresponding implementation file is named
"quicksort3.C". Renaming the implementation file would hopelessly
confuse the compiler.
See main program which uses the
Quicksort template and sample run.
This example shows that we can write one generic Quicksort template and
have it work with data of type int, float and
- We can also write a generic Quicksort using virtual functions and
dynamic binding. First, we declare an abstract base class called Ordered.
The idea is that any object from a class derived from Ordered can be
ordered and thus can be sorted. (See Ordered class declaration.) From Ordered
we derive the classes Integer and String. The Ordered class declares the
virtual functions clone(), cmp() and print()
which is all we need to do Quicksort. The id() function is used
for run-time type checking, as we did in Lecture 19 for generic lists. Note that we
do not need a virtual swap function because we intend to sort an array of
Ordered pointers. Swapping these pointers can be done directly. Since
Ordered is an abstract base class, we don't have an implementation of these
virtual functions. The derived classes must implement these functions.
(See implementation of Integer and String.)
- Now we can write a generic Quicksort function using dynamic
binding. The main program and
sample run show that we can
even sort an array that has pointers to Strings and Integers (this is
called working with heterogeneous data).
- Discussion on pros and cons of templates versus dynamic binding. Using
templates creates a bigger program since we have a different function for
each type. We also need the source code for a template at compile time.
With dynamic binding, we only need the header files at compile time.
Dynamic binding lets us work with heterogeneous data, templates do not (or
at least not very easily). We need to define lots of classes when we work
with dynamic binding and virtual functions --- this is the major
disadvantage of working with virtual functions. Finally, invoking
virtual functions is a bit slower since we have to follow a few
pointers to find the virtual function table.
- We convert our generic list class to templates. This is mostly a
syntactic process. See new header
file and implementation.
The following examples show the typical use of the GenList template:
- One problem we have with this version of GenList is with empty lists.
Suppose the client requests the first item of an empty list. We can't just
return NULL, since the return type might not be a pointer (e.g., when we
have a list of int.) The approach here is to return whatever item
the default constructor gives us. We let the client worry about checking
the length of the linked list. (The compiler might complain because
int does not have a default constructor.) An alternative
approach, which we use in the next version of GenList, is to have functions
like begin() return an integer value that is used for error
checking. The value of the first item of the linked list, if any, is
"returned" via a reference parameter.
- One tricky issue with templates is figuring out how to declare a
template class to be the friend of another template class. In this case we
need a forward class declaration. In the following example, (which we did
not discuss in detail in lecture) we define an Iterator class to be the
friend of our GenList class. See header
file and implementation.
The following examples show how we would use the Iterator class
to traverse a linked list:
24 Nov 1998 14:12:29 EST
to Fall 1998 CMSC 202 Section Homepage