The Standard
Template Library
and
a few details on how it is implemented
A example container class
Our Example
container class is called Linked
It is a toy
class, not part of the STL
We look at it as an
example of how container classes are implemented in the STL
We will start with a clients view
what the class
needs to provide to users.
Since we dont know what the data type of our client
is, we must make our class a template
Lists will be instantiated like this:
Linked<int>
intList;
or
Linked<Employee> employeeList;
Overall view of Linked class
Our Linked class will be made up of these parts
The data members
An embedded struct
to hold the node
The struct will have two
parts: a generic item, and a pointer to the next node
The
private data members of the class
a pointer to the head of the list and
an int to keep track of
how many items are in the list
A nested Iterator class
Must define all the operations for traversing and
comparing a linked list
Some of these will be overloaded operators
The member functions (limited for now)
A
constructor, push_front, size, begin, end
Linkeds
struct & data members
template<class T>
class Linked
{ protected:
struct
Node // data members of structs are
public
{ T item; Node* next; };
//end struct Node
Node* head;
long length;
//
member functions, etc. go here
class
Interator {
all its data & member functions
};
}; // end class Linked
The Linked class functions
For our toy class, we will only specify five member
functions
Prototypes of
member functions:
template<class T>
//or Comparable or
whatever
class Linked
{ protected:
struct
Node // data members of structs are public
{ T item; Node* next; };
//end struct Node
Node* head;
long length;
class Interator
{
all its data & member functions };
public
Linked( ); // constructor makes empty list
long size( ) const; //returns
the number of items in the list
void push_front(const
T& newItem); // inserts a new item at the front of the list
Iterator begin( ); // returns an
iterator positioned at the front of the list
Iterator
end( ); // returns an iterator positioned just after the end of the list
};
Implementing Linkeds
member functions
The Node struct
struct Node
{ T
item;
Node* next;
}
The
constructor
Linked( )
{ head = NULL;
length = 0; }
The size
member function
long size( )
const
{
return length;}
The push_front member function inserts a new item at the front of the
list
void push_front(const T& newItem)
{ Node * temp = new Node;
temp->item = newItem;
temp->next = head;
head = temp;
length++;
}
The begin
member function will return a
iterator positioned at the front of the list
Iterator
begin( )
{ return Iterator(head); }
The end
member function will return a
iterator positioned at the end of the list
Iterator
end( )
{ return Iterator(NULL); }
Iterators for Linked class
An iterator is an object that allows the client to
access each item in the container.
An iterator class is embedded in almost every
container class
The iterator class has member function to
overload these four operators
operator ++ advances the calling iterator object to the
next item in the container
There
are pre and post increment operators
operator* dereferences
the item where the iterator is currently positioned
Operator = =
and != to test for equality
An example using Linked
int main( )
{ Linked<float> salaryList;
float
salary, total = 0.00;
cout
<< "Please enter a salary; the sentinel is -1.00: ";
cin >>
salary;
while (salary
!= -1.00)
{
salaryList.push_front (salary);
total +=
salary;
cout
<<"Please enter a salary; the sentinel is -1.00: ";
cin
>> salary; }
float average;
if (salaryList.size(
) > 0)
average
= total / salaryList.size( );
cout
<< "Here are the above-average salaries:" << endl;
Linked<float>::Iterator itr;
for (itr
= salaryList.begin( ); itr
!= salaryList.end( ); itr++)
if (*itr > average)
cout
<< *itr << endl;
}
What private data members will the class
Iterator need?
It will need a pointer to a Node.
Implementation of Iterator
The Iterator
class has only one data member
protected:
Node* nodePtr; //
a pointer to a Node
Iterator (Node* newPtr)
{ nodePtr = newPtr; } //
this constructor should be protected (or private)
public:
Iterator( ) {
} // default constructor
Implementing the
member functions of the Iterator class
Overloading the =
= operator.
bool
operator== (const Iterator& itr) const
{return nodePtr =
= itr.nodePtr;
} // overloading = =
Overloading the != operator
bool operator!= (const Iterator& itr)
const
{
return nodePtr != itr.nodePtr; }
// overloading !=
Overloding the * (dereference) operator
T& operator*( ) const
{
return nodePtr ‑>
item; } // overloading *
The
++ (increment) operator
The compiler must be able to tell the difference
between post increment and pre increment
It cannot do this if their signatures are the same
So the post increment operators signature includes an
int argument; this is a dummy argument, solely for
the compilers sake
Iterator operator++(int) // post increment uses a dummy argument
Iterator operator++( ) // preincrement has no argument
Look at pre and post increment
Suppose you have
this statement
num = ++I + num;
How is it
different than this statement
num = I ++ + num;
To see, give num and I values
Post increment is not done until AFTER the statement
completes execution, so the I used in the statement
has not been incremented.
Implementing the
member functions of the Iterator class (cont)
Post increment operator
Iterator operator++(int)
{ Iterator temp = *this;
nodePtr =
nodePtr ‑> next;
return temp;
} // post‑increment ++
Pre increment operator
Iterator& operator++(
)
{ nodePtr
= nodePtr ‑>
next;
return *this;
} // pre‑increment ++
Additional member functions of Linked
So far we have implemented five member function for
Linked: Linked(
), size( ) push_front( ), begin( ) and end( )
What other functions would be necessary or desirable?
Delete from the front of the list
Overload the assignment operator
Implement a destructor
Implement a copy constructor
IN class assignment (quiz)
Get together in groups of two or three
Look over than handout which has implemented the code
we have been talking about
Write the code for member functions of the class
Linked to do the following:
Delete from the front of the list
Overload the assignment operator
Implement a copy constructor
Implement a destructor
Implementing pop_front
What should it return? What are the arguments?
We need a temporary pointer to point to the first node
in the list
We then make head point to the second node in
the list
Then we delete the node pointed to by the temporary
pointer
Then we decrease length.
How should operator= be overloaded?
How it would be used:
Assume Linked<Employee> Kmart and
Linked<Employee> WalMart have been
declared and populated.
An assignment statement would look like this:
WalMart = Kmart; Will a shallow copy work?
How should it
be implemented?
First, we must
delete all the nodes in the WalMart list. Why?
Next, we must we
need to copy the Kmarts nodes to the WalMarts list.
We
can traverse through Kmarts list, copying each node as we go, using push_front(temp->item
)
Use a for loop to do this
Problem? The list
will be reversed
So
then, we must copy it back to get it in the same order
This
means we must use a temporary list for the first copy
Implementation of operator=
void operator= (const Linked<T>& rhsList)
{
Linked<T> tempList; // for the reversed list
Node* temp;
while (head
!= NULL)
pop_front(
); // Destroy the calling object:
for (temp
= rhsList.head;
temp != NULL; temp = temp ‑>
next)
tempList.push_front
(temp ‑> item);
for (temp= tempList.head; temp !=
NULL; temp = temp ‑>
next)
push_front
(temp ‑> item);
}
// overloading =
Implementation
of the copy constructor
It is just like the assignment operator, except no
list has to be destroyed.
The destructor
Destructors return to the operating system the dynamic
memory a program requested.
They are automatically
called for an object when that object goes out of scope.
This relieves the
programmer from having to remember to delete dynamic objects when those objects
go out of scope.
There are several ways to implement the destructor for
Linked:
Traverse the list
with a for loop, deleting each node as we go
Call pop_front( ) until head is NULL
Destructors should be written for classes whose
objects contain dynamically allocated memory.
Overloading the assignment operator and copy
constructor
The assignment operator and copy constructor needs to
be overloaded for classes that have data members that contain pointers.
What is the difference between them? they both make copies
The copy constructor is used when one objects already
exists, and we want to create another object that is a copy of it
The assignment operator is used when both objects
already exist, and we want to copy one into another
Example of copy constructor and assignment
operator
Suppose we have an object of type Linked<Person>
that already has some data in it.
Linked<Person> yourList; // assume already has data
We want to create another list that is a copy of yourList. We use a copy constructor
Linked<Person>
myList(yourList);
I have introduced errors into mylist,
and I want to start over, copying yourList. Use the assignment
statement
myList = yourList;