UMBC CMSC202, Computer Science II, Fall 1998,
  Sections 0101, 0102, 0103, 0104  
 21. Templates 
 Tuesday November 17, 1998 
[Previous Lecture]
[Next Lecture]
 Assigned Reading:  10.1-10.6
 Handouts (available on-line):
Programs from this lecture:
 Topics Covered:
 
    
    
    
-  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 
    BString.
    
     
     
-  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:
     
[Previous Lecture]
[Next Lecture]
Last Modified:
22 Jul 2024 11:28:48 EDT
by
Richard Chang
Back up
to Fall 1998 CMSC 202 Section Homepage