1 linked lists iii template chapter 3. 2 objectives you will be able to: write a generic list class...
TRANSCRIPT
1
Linked Lists IIITemplate
Chapter 3
2
Objectives
You will be able to: Write a generic list class as a C++
template. Use the template in a test program.
3
Issues in the int List Class
The list can only hold integers.
Solution: Make it a template.
4
Templates
Templates are a feature in C++ that permit code to be more reusable.
They have blanks, called parameters, that can be automatically filled in with type names at compile time.
Rather than having to define separate classes for lists of ints, doubles, Circles, Dogs, Cats, etc., we can define a single List template.
A user of the template can supply the name of the class that will be the data in list nodes.
The compiler handles the substitution of the class name specified by the user for the parameter into the template definition.
Result is a List class specialized for the user’s class.
5
Limitations of Template
A class used as a template parameter must meet certain requirements.
Must implement all operators used by the template methods. Typically
= (Assignment operator) Copy constructor
6
Templates
We have two kinds of templates in C++. Function templates. Class templates.
In each, parameters can be specified for one or more types. The parameters are used as if they were real
type names.
The compiler substitutes real type names, specified by the user, for the parameters when the template is used.
7
C++ Templates
The word template is a C++ keyword
In front of a function definition, it specifies that what follows is … a pattern for a function definition not a real function definition.
Type parameters appear within angle brackets ( < > ) before the function definition.
Normal function parameters appear within parentheses, as in normal function definitions.
8
Caution
A function template cannot be split across files. Specification and implementation must be in
the same file. Just a .h file. No .cpp file.
9
A Function Template
template <class T> T is a parameter
void Swap (T &first, T &second)
{
T temp = first;
first = second;
second = temp;
}
The keyword typename can be used instead of the keyword class in the first line.
10
Function Template Instantiation
When the compiler encounters a call to a function defined as a template, it generates a real function definition substituting the type(s) of the function arguments for the template parameter(s).
The function call looks exactly like a call to a normally defined function.
Example: swap (a[i], a[i+1]);
11
Class Templates
We can define templates for classes as well as for functions.
Specify one or more template parameters in front of the class definition.
The class definition uses the parameters as if they were real class names.
Real class names must be provided as values for the parameters whenever the template is used.
12
General Form Of Class Template Declaration
template <class TypeParam1, class TypeParam2,..., class TypeParamN>class SomeClass{ // ... members of SomeClass ...};
Within the class definition, the class parameters TypeParam1, TypeParam2, … TypeparamN can be used as if they were real class names.
The parameter names can be any valid C++ name. (Same rules as for variable names.)
When the class is used, real class names will be provided and substituted for the parameters.
class is a C++ keyword here.
13
Alternative Form
Keyword typename can be used instead of
keyword class in the template parameter list.
template <typename TypeParam1, typename TypeParam2,..., typename TypeParamN>class SomeClass{ // ... members of SomeClass ...};
14
Instantiating Class Templates
Instantiate the template by writing a declaration of form
SomeClass<Type> objectName;
where “Type” represents a real class name and SomeClass is the name of the template class.
Passes Type as an argument to the class definition template.
Examples: Stack<int> intStack;Stack<string> stringStack;
Compiler will generate two distinct definitions of Stack Two instances of the class definition One for ints and one for strings.
15
Rules For Class Templates
1. Member functions outside the class declaration must be function templates.
2. Member functions must be defined in the same file as the class declaration.
3. All uses of the template class name as a type must be parameterized.
16
Convert intDLList into a List Template
Create a new project. List_Template_Demo
Copy the files from intDLList2 into the project directory.
http://www.cse.usf.edu/~turnerr/Data_Structures/Downloads/2011_01_24_Doubly_Linked_List_2/
Add the .h file to the project. Rename as DLList.h
17
Convert intDLList into a List Template
Modify the existing code for intDLList to make it a template.
Have to copy the function definitions from the .cpp file into the .h file.
Replace int by a class parameter.
Replace class names by new parameterized class names.
18
The Node Class Definition
//************************ DLList.h *****************// Doubly-linked list template
#ifndef DLLIST_H#define DLLIST_H
template<class T>class DLLNode {public: T info; DLLNode<T> *next; DLLNode<T> *prev;
DLLNode(T el, DLLNode<T> *ptr1 = 0, DLLNode<T> *ptr2 = 0) { info = el; next = ptr1; prev = ptr2; }};
19
Problem with the Listhead
In the intDLList we create the Listhead with an info value of 0. The value is never used.
We can't do this with a template. For an arbitrary class, T, 0 might not be
a valid value. We need a constructor for class
DLLNode that doesn't specify a value for info.
Leaves info uninitialized in the Listhead.
20
Default Constructor for DLLNode
Add to DLLNode class defintion:
DLLNode()
{
next = 0;
prev = 0;
}
21
DLList Class Definition
template<class T>
class DLList
{
private:
DLLNode<T>* ListHead;
public:
DLList()
{
ListHead = new DLLNode<T>();
ListHead->next = ListHead;
ListHead->prev = ListHead;
}
22
DLList Class Definition
DLList(const DLList<T>& original);
DLList& operator=(const DLList<T>& original);
~DLList();
int isEmpty() const
{
return ListHead->next == ListHead;
}
void addToHead(const T&);
void addToTail(const T&);
T deleteFromHead(); // Delete the head and return its info;
T deleteFromTail(); // Delete the tail and return its info;
void deleteNode(const T&);
bool isInList(const T&) const;
void printAll() const;
};
23
Destructor
template<class T>DLList<T>::~DLList(void){ while (!isEmpty()) { DLLNode<T> *p = ListHead->next->next; delete ListHead->next; ListHead->next = p; }}
24
addToHead
template<class T>void DLList<T>::addToHead(const T& el) { DLLNode<T> *p = new DLLNode<T>(el);
p->next = ListHead->next; p->prev = ListHead;
ListHead->next->prev = p; ListHead->next = p;}
25
addToTail
template<class T>void DLList<T>::addToTail(const T& el) { DLLNode<T> *p = new DLLNode<T>(el);
p->next = ListHead; p->prev = ListHead->prev;
ListHead->prev->next = p; ListHead->prev = p;}
26
deleteFromHead
template<class T>T DLList<T>::deleteFromHead() { if (isEmpty()) { throw("Attempt to delete from empty list"); } T el = ListHead->next->info;
DLLNode<T> *tmp = ListHead->next; ListHead->next->next->prev = ListHead; ListHead->next = ListHead->next->next;
delete tmp; return el;}
27
deleteFromTail
template<class T>T DLList<T>::deleteFromTail() { if (isEmpty()) { throw("Attempt to delete from empty list"); } T el = ListHead->prev->info;
DLLNode<T> *tmp = ListHead->prev; ListHead->prev->prev->next = ListHead; ListHead->prev = ListHead->prev->prev;
delete tmp; return el;}
28
deleteNode
template<class T>void DLList<T>::deleteNode(const T& el) { DLLNode<T> *p = ListHead->next; while (p != ListHead && p->info != el) { p = p->next; }
if (p == ListHead) { return; // It's not there. Claim success! }
// p points to node to be deleted. p->prev->next = p->next; p->next->prev = p->prev; delete p;}
29
isInList
template<class T>bool DLList<T>::isInList(const T& el) const { DLLNode<T> *p = ListHead->next; while (p != ListHead && p->info != el) { p = p->next; }
return p != ListHead;}
30
printAll
template<class T>void DLList<T>::printAll() const {
if (isEmpty())
{
cout << "List is empty\n";
return;
}
DLLNode<T> *p = ListHead->next; while (p != ListHead) { cout << p->info << endl; p = p->next; }
cout << endl;}
31
Copy Constructor
// Copy constructor
template<class T>
DLList<T>::DLList(const DLList<T>& original)
{
ListHead = new DLLNode<T>();
ListHead->next = ListHead;
ListHead->prev = ListHead;
// Copy the original list
DLLNode* p = original.ListHead->next;
while (p != original.ListHead)
{
addToTail(p->info);
p = p->next;
}
}
32
Assignment Operator
// Assignment operator
template<class T>
DLList<T>& DLList<T>::operator=(const DLList<T>& original)
{
if (this == &original) // Check for self assignment
{
return *this;
}
while (!isEmpty()) // Delete the current list contents
{
deleteFromTail();
}
delete ListHead;
33
Assignment Operator
ListHead = new DLLNode<T>();
ListHead->next = ListHead;
ListHead->prev = ListHead;
// Copy the original list
DLLNode<T>* p = original.ListHead->next;
while (p != original.ListHead)
{
addToTail(p->info);
p = p->next;
}
return *this;
}
34
Testing the Template
Adapt the test driver for intDLList to use the DLList template.
Parmeterize the template for int. Results should be identical to
previous.
35
main.cpp
#include <iostream>
#include "DLList.h"
using namespace std;
int main()
{
DLList<int> myList;
...
myList = new DLList<int>();
...
myList = new DLList<int>();
...
Everything else is unchanged.
36
Program Running