Transcript Lecture 9

COSC3557: Object-Oriented
Programming
Haibin Zhu, Ph. D.
Professor of CS, Nipissing
University
1
Lecture 9
 Container
2
classes & STL
Contents

General principles about Containers



C++ STL




Everything is an object!
C++ Container classes


3
Containers
Iterators
Algorithms
Function Object:


Substitution/Downcast/Overriding/Generic
Object-Based/Template based
List
Map
Containers in Dynamically
Typed Languages
Collection classes are simple to write in
dynamically typed languages, Since all
variables are polymorphic. Containers simply
hold values in variables (which can hold
anything), and when they are removed from
the container they can be assigned to any
variable.
 Dynamically typed languages have
historically come with a rich set of container
classes in their standard library.

4
Tension between Strong
Typing and Reuse
The situation is very different when we move
to statically typed languages. There, the
strong typing can get in the way of software
reuse.
 type

Link = Record

value : integer

nextelement : ^ Link

end;
 What happens when we need a linked list of
doubles? or of a user defined type?

5
Can OO Techniques
Solve This
 Can
we bring any of the OO techniques
(subsitution, polymorphism) into the
solution of this problem? We examine
three techniques:
 Using Substitution and Downcasting
 Using Substitution and Overriding
 Using Templates (or Generics)
6
Using Substitution and
Downcasting










7
In Java and other languages, (almost) all values can be stored
in a variable of type Object.
Therefore, we write containers that store Object values.
Problem. Requires a cast when a value is removed from the
container.
Vector aVector = new Vector();
Cat Felice = new Cat();
aVector.addElement(Felice);
...
// cast used to convert Object value to Cat
Cat animal = (Cat) aVector.elementAt(0);
Worse problem, typing errors are detected when a value is
removed from the collection, not when it is inserted.
Generic Algorithms versus
Encapsulation
 Object-Oriented
programming holds
encapsulation as an ideal, bundling all
actions in one place. It can make for ``fat''
classes.
 The STL separates data structures and
algorithms. The data structures are
relatively small. The algorithms are many.
They can be mixed and matched.
 It allows for a much smaller class library.
8
Using Substitution and
Overriding
 In
certain situations we can eliminate
the downcast, replacing it with
overriding.
 This only works, however, if you can
predict ahead of time what operations
you want to do on a collection.
9
An Example, Java Window
Events








10
A good example is the way that window events are handled in
Java. Each window maintains a list of listeners, each listener
must implement a fixed interface (WindowListener).
public class CloseQuit extends WindowAdapter {
// execute when the user clicks in the close box
public void windowClosing (WindowEvent e) {
System.exit(0); // halt the program
}
}
When an event occurs the window simply runs down the list of
listener, invoking the appropriate method in each. No
downcasting required.
A Third Alternative, Generics















11
Generics, as we described in the last chapter, are a third approach.
template <class T> class List {
public:
void
addElement (T newValue);
T
firstElement ();
private:
Link * firstLink;
private class Link { // nested class
public:
T
value;
Link *
nextLink;
Link (T v, Link * n) : value(v), nextLink(n) { }
};
};
Allow for both strong typing and reuse.
Collection Traversal














12
Here is another difficult problem. How to you allow access to elements
of a collection without exposing the internal structure?
Consider the conventional solution:
var
aList : List;
(* the list being manipulated *)
p : Link;
(* a pointer for the loop *)
begin
...
p := aList.firstLink;
while (p <> nil) do begin
writeln (p.value);
p := p^.nextElement;
end;
Needed to expose the link type, and the field nextElement.
Can we avoid this problem?
Two Solutions
 There
are two common solutions:
 · Create
an iterator; an object that
facilitates access to elements and
enumeration over the collection.
 · The visitor. Bundle the action to be
performed as an object, and pass it to the
collection.
13
Iterator
 An
iterator is an object that has two major
responsibilities:
 Provide
access to the current element
 Provide a way to move to the next element
14
Alternative, the Visitor
An alternative to iterators is the idea of a visitor.
Requires the ability to bundle the action to be
performed into an object, and hand it to the
collection.
 This is most common technique used in Smalltalk

 aList

15
do: [:x | ('element is' + x) print ].
The block is passed as argument to the list, which
turns around and executes the block on each
element.
List
A
set of sequentially organized
elements.
A
specific type of graph, where each node
except the first has a single preceding
node, and each node except the last has a
single following node.
 Contains 0-n nodes.
 Implementation: array and linked list.
16
How to have lists with
different types
 By
template
 With the same structure, we can have
integer, float, or character string as a
value of a node.
 But, can you have a list with values in
different types by C++?
Yes! But with the same base class.
17
Template-based List
head
tail
info
next
Same class
18
Tnode
template <class T>
class Tnode {
friend class TList<T>;
value next
public:
Tnode():next(0){ }
Tnode( const T & val );
Tnode<T> * Next() const;
friend ostream & operator <<(ostream & os,
const Tnode<T> & N);
private:
T value;
// data stored in node
Tnode * next; // points to next node
};
19




















20 
TList
template <class T> class TList {
public:
TList );
~TList );
int Advance ); // Return 0 if current is already at the end of the list; //otherwise, current will point
to the next node and return 1.
void Append const T & nodeVal ); // Add a new node to the end //of the list.
void Clear ); // Remove all nodes.
T Get ) const; // Get the data at the current position.
void GoLast ); // Set current to the last node in the list.
void GoTop ); // Set current to the header node.
int AtEnd ); // return true if at end.
void InsertAfter const T & nodeVal ); // Insert new node after current one.
int IsEmpty ) const; // Return 1 if the list is empty; otherwise,return 0.
void Prepend const T & nodeVal ); // Insert a node at the beginning of the list.
void Replace const T & newVal );
// Replace the data in the current node.
private:
Tnode<T> * head;
// head node
Tnode<T> * tail;
// tail node
Tnode<T> * current; // current node
};//Tlist.cpp
value next
head
tail
current
value null
Object-Based List
 In
this section, we will introduce the
method to design a List not based on
template.
 Also, we implement a linked list that
means, every node in the list has links
to the previous one and the next one.
data next
21
Template-based List
head
tail
info
22
next
Different classes
The structure
ONode
Student
23
Faculty
.....
Adminstrator
ONode
class ONode {
friend class OList;
public:
ONode();
virtual ~ ONode() { }
ONode * Next() const; // Return pointer to next node.
virtual int operator ==( const ONode & N ) const = 0;
friend ostream & operator << (ostream & os, const ONode & N );
friend istream & operator >> (istream & inp, ONode & N );
private:
virtual void printOn( ostream & os ) const = 0;
virtual void readFrom( istream & is ) = 0;
ONode * next; // pointer to next node
};
24
OList
25
class OList {
public:
OList();
~OList();
int Advance(); // Return 0 if current is already at the end of the list; //otherwise, current
will point to the next node and return 1.
void Append( const ONode & nodeVal ); // Add a new node to the end of the list.
void Clear(); // Remove all nodes.
ONode Get() const; // Get the data at the current position.
void GoLast();
// Set current to the last node in the list.
void GoTop();
// Set current to the header node.
void InsertAfter( const ONode & nodeVal ); // Insert new node after current one.
int IsEmpty() const; // Return 1 if the list is empty; otherwise,return 0.
void Prepend( const ONode & nodeVal ); // Insert a node at the beginning of the list.
void Replace( const ONode & newVal ); // Replace the data in the current node.
friend ostream & operator <<(ostream &, const OList &);
private:
ONode * head;
// dummy head node
ONode * tail;
// dummy tail node
ONode * current; // current position
};
What is the STL?



26
The STL is a rich collection of standard
data structures, recently added to C++
Will elevate data structures to the level
of, say, the I/O stream package (i.e.,
something taken for granted)
In many ways, it is an beyond objectoriented design, yet it is powerful and it
works.
A very brief social history





27
The C++ Standard Library == STL + other stuff e.g.,
auto_ptr
The STL is primarily the design of one person, Alexander
Stepanov, many have worked on it subsequently
Stepanov was a colleague of Bjarne Stroustrup at AT&T
Research in the 1980s. Later he moved to HP and then
SGI, taking the STL “ownership” with him.
Stroustrup liked the STL and lobbied for its inclusion in the
1998 ANSI standardization of C++.
The requirements on an implementation of the STL (as
imposed by the ANSI standard) are tough; any correct and
(compliantly) efficient implementation is very complex.
Design Philosophy

A collection of useful, efficient, type-safe, generic
containers



A collection of useful, efficient, generic algorithms
that operate on iterators


28
A container has (almost) no understanding of the element
type, Exception: can-be-sorted via some operator<
Each container should define its own iterators.
“Generic” => algorithm knows nothing about the structure it’s
operating on, apart from the fact that it can be traversed by
an iterator, and knows almost) nothing about the elements
in the structure
Define container methods only when the generic algorithms
are unsuitable or much less efficient
C++ STL
The Standard Template Library, or STL, is a
C++ library of container classes, algorithms,
and iterators.
 Containers are classes whose purpose is to
contain other objects.
 It provides many of the basic algorithms and
data structures normally used in programs.

Algorithms
29
Iterators
Containers
Containers and algorithms
 Sequences
 continuous
blocks of objects
 Indexed by integers
 vector, list, deque,
 Associative
 Might
containers
be indexed by any class of objects
 set, multiset, map, multimap
30
Vectors
List
0
1
0
2
3
4
5
1
2
3
4
31
Deque
0
1
2
3
4
5
Map
Set
32
keys
values
Container
Sequence
Vector
33
List
Associative Container
deque
Set
Multiset
Map
Multimap
C++ STL Algorithms(1)




34
Non-Mutating Sequence Operations. Algorithms like
count and search which do not modify the iterator or
its associated container.
Mutating Sequence Operations. Algorithms like
copy, reverse, or swap which may modify a
container or its iterator.
Searching and Sorting. Sorting, searching, and
merging algorithms, such as stable_sort,
binary_search, and merge.
Set Operations. Mathematical set operations, such
as set_union and set_intersection. These algorithms
only work on sorted containers.
C++ STL Algorithms(2)



35
Heap Operations. Heaps are a very useful and
efficient data structure that is often used to
implement priority queues. The STL provides
facilities for making heaps and using them.
Numeric Operations. The STL provides a few
numerical routines to show how the STL might be
used to provide a template-based numeric library.
The STL provides algorithms for: accumulate,
inner_product, partial_sum, and adjacent_difference.
Miscellaneous Operations. This final category is for
algorithms, like min and next_permutation that don't
quite fit in the above categories.
An algorithm example










36
vector<int> arr(3);
arr[0] = 5;
arr[1] =10;
arr[2] = arr[0] + arr[1];
reverse(arr.begin(), arr.end());
int A[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
reverse(A, A+8);
for (int i = 0; i < 10; ++i)
cout << "A[" << i << "] = " << A[i];
//reverse.cpp
Iterators
 Basic
problem - how do you allow
access to elements of collection,
without knowing how the collection is
organized?
 Solution, define a new data type
specifically for creating loops
 A large number of algorithms are provided
by the standard library, all built using
iterators.
37
How do you describe a
range of values
 Notice
how a range of values is often
described by a starting value and a
past-the-end value.
 The past the end value is not part of the
collection, but just a marker.
38
Begin and End
 By
convention, containers return a starting
value in response to begin(), and a pastthe-end value in response to end().
 For
example, to shuffle a vector of values:

random_shuffle
(aVector.begin(), aVector.end(),
randomInteger);
39
Iterators are generalized
pointers
Vectors
begin
List
Dequeue
begin
begin
end
end
end
40
Iterator organization
 Iterators
are classified into five
categories: forward, bidirectional,
random access, input, and output.
 The description of container classes
includes the category of the iterator
types they provide.
 The description of generic algorithms
includes the iterator categories they
work with.
41
What must iterators do














42
To see what iterators must do, consider a typical algorithm:
template <class InputIterator, class T> InputIterator find
(InputIterator first, InputIterator last, T & value)
{
while (first != last && *first != value) ++first;
return first;
}
Could be used to find values in an array, or in a list:
int data[100];
...
int * where = find(data, data+100, 7);
list<int> aList;
list<int>::iterator where = find(aList.begin(), aList.end(), 7);
//iter.cpp
Iterator Operations




43
An iterator can be compared for equality to another iterator. They
are equal when they point to the same position, and are otherwise
not equal.
An iterator can be dereferenced using the * operator, to obtain the
value being denoted by the iterator. Depending upon the type of
iterator and variety of underlying container, this value can also
sometimes be used as the target of an assignment in order to
change the value being held by the container.
An iterator can be incremented, so that it refers to the next element
in sequence, using the operator ++.
What makes iterators possible is that all of these can be
overloaded.
Faction objects
 Function
objects are STL's way of
representing "executable data".
 In C++, the function call operator
(parenthesis operator) can be
overloaded. Allows for creation of
objects that can be used like functions.
 In a function object, at least one
parenthesis operator () is defined.
44
A function is an object











45
Objects can take arguments computed at run-time, specialize
functions in a way that simple functions cannot:
class biggerThan {
public:
biggerThan (int x) : testValue(x) { }
const int testValue;
bool operator () (int val)
{ return val > testValue; }
};
list<int>::iterator firstBig =
find_if (aList.begin(), aList.end(), biggerThan(12));
In functional languages, this kind of object is sometimes known as a
curry. //bigthan.cpp
Function Object Examples












46
#include <iostream>
class threshold {
double val;
public:
threshold( double v): val(v) {}
bool operator()( double y){ return y < val; }
} reallySmall( 1.e-8 ), small(1.e-3);
int main() { double x;
while ( std::cin >> x )
std::cout << x << " " <<
(reallySmall(x) ? "tiny" : small(x) ? "small" : "big") << '\n';
}//funobj.cpp
The Visitor in C++ in the STL








class printingObject {
public:
void operator () (int x)
{
cout << "value is " << x << endl;
}
};
printingObject printer;



47
// create an instance of the function object
for_each (aList.begin(), aList.end(), printer);
The function for_each passes the object to element
element in the collection. //funo.cpp
C++ List
 C++
provides many class templates of
containers including vector, list, set,
deque, map, queue, priority_queue,
and stack. They can be parameterized
into any class of these to deal with a
sequence of objects.
48
The interface of List
Member function
name
49
Descriptions
back()
Get the last element
begin()
Get the pointer to the first element
clear()
Erase all the elements
end()
Get the pointer to one past the last element
erase(first, last)
Erase from first to last
erase(p)
Remove the element at p
remove(e)
Remove the element equal to e
front()
Get the first element
insert(p, x)
Add x before p
push_back(e)
Adds an element e to the end of a list
An Example of List
#include <list>
//…
list<int> L;
L.push_back(0);
// Insert a new element at the end
L.push_front(0);
// Insert a new element at the beginning
L.insert(++L.begin(),2);
// Insert "2" before position of first argument
// (Place before second argument)
L.push_back(5);
L.push_back(6);
list<int>::iterator i;
for(i=L.begin(); i != L.end(); ++i) cout << *i << " ";
cout << endl;
//list.cpp
50
The algorithm library
 The
header file for these functions is
<algo.h> or <algorithm>.
 The STL algorithms are generalized
function templates.
 //alg.cpp
51
Function name Descriptions
binary_search
Search an object with a binary search algorithm. If the
object is in the sequence return true. Otherwise, return
false.
copy
Copy one sequence of objects to another.
count
Returns the number of objects in a sequence.
equal
Returns true if the objects positioned in a subsequence are
equal to the objects of another subsequence. Otherwise,
returns false.
find_if
Returns true if there is an object that satisfy the predicate
provided. Other wise, return false.
for_each
Apply the function provided to each object in a sequence.
The function is as the returned value.
lower_bound
Returns the iterator pointing the first object equal to the
object provided. If there is no such object, an iterator
pointing to the first object that is grater than the object
provided. If there is no such an object, a pointer to a
sentinel is returned.
52
Max
Returns the maximum object of the two objects provided.
Merge
Merger two subsequences to the 3rd place.
Min
Returns the minimum object of the two objects provided.
random_shuffle Rearrange the object sequence randomly.
remove
Removes an object in the sequence that is equal to the object
provided.
replace
Replace occurrences of the object with another object.
reverse
Reverse the sequence of objects.
sort
Sorts the sequence of objects.
swap
Swaps the two objects provided.
upper_bound
Returns the iterator pointing the last object equal to the object
provided. If there is no such object, an iterator pointing to the
first object that is grater than the object provided. If there is no
such an object, a pointer to a sentinel is returned.
53
Map

A map is a sequence of <key, value> pair that
provides for fast retrieval based on the key.
A map
map<T1,T2>
….
Pair objects
pair<T1,T2>
Key
Value
pair<T1,T2>
Key
Value
……
……
pair<T1,T2>
54
Key
Value
……
Set
 Set
is a Sorted Associative Container
that stores objects of type Key.
 Set is a Simple Associative Container,
meaning that its value type, as well as
its key type, is Key.
 It is also a Unique Associative
Container, meaning that no two
elements are the same.
55
Map examples


















56

int main() {
string as[] = {"A+","A","A-","B+","B","B-","C"}; //passing grades
typedef set<string> SSet;
// set of strings
SSet acceptable( as, as + sizeof(as)/sizeof(as[0]) );
// construct set using all elements of the array
typedef map<string, SSet> SMap;
// map strings into SSets
SMap m;
ifstream infile("Source.txt");
for(string n, c, g; infile >> n >> c >> g ; ) // name course grade
if ( acceptable.count( g ) /* > 0 */ )
// if grade is in passing set
m[n].insert( c );
for(SMap::iterator it = m.begin(), stop=m.end(); it != stop; it++) {
cout << it->first << ": ";
// output person's name
for(SSet::iterator p = it->second.begin(), q=it->second.end(); p != q; p++)
cout << *p << ' ';
// output each course passed
cout << '\n';
infile.close();
}
}//map.cpp
Summary
 General
Principles on Containers
 Substitution/Downcast/Overriding/Generic
 Object-Based/Template
based
 STL
 Generic
algorithms
 http://www.sgi.com/tech/stl/table_of_cont
ents.html
 Container
classes
 List
 Map
 Everything
57
is an object!