Upload
clarence-murphy
View
225
Download
0
Embed Size (px)
Citation preview
CE00314-2Further Programming Concepts in C++
Lecture 6
Collections & Templates
Introduction
Part 1 Collections Static - Dynamic Template definition Function templates Class templates
Part 2 Adaptable collections Further inheritance
Collections
Arrays Dynamic collections
Linked lists Constructed within application (specific) Generic linked list class Template implementation of generic l. list
Standard Template Library contains Vectors Linked Lists Other STLs
Array of accounts Array initialisation
int b[5] = {75,25,100,-45,60};
Account acct[3] = {Account(500,5,0.6), Account(), Account(100.0) };
COLLECTIONS
An array of various accounts
main(){Savings acc1(100.0);Time acc2(500.0, 100.0);Investment acc3(101.5, 6.5);
Account* staffacct[3] = { &acc1, &acc2, &acc3}
for(i = 0; i<3; i++){
staffacct[i]->print();}
Arrays and new
Arrays can be created with new int* p = new int[10]; elements are accessed using subscripts
p[0],p[1] ... similarly for objects:
Account * acs = new Account[20];cout<< acs[0]->balance();
Deleting Objects
Once an object created with new is finished it can be destroyed using delete
delete ac1; If the pointer points to an array it is necessary
to tell C++ this by writing: delete [ ] p;
Dynamic Collections
• Arrays are a fixed size although can be resized dynamically by using memory management features used in C
• Dynamic structres ccccna be used to allow collection to shrink and grow dynamically
• Different implementations exist
Comparing Implementations
Fixed size versus dynamic size A statically allocated array
Prevents the enqueue operation from adding an item to the queue if the array is full
A resizable array or a reference-based implementation
Does not impose this restriction on the enqueue operation
Comparing Implementations
Pointer-based implementations A linked list implementation
More efficient The ADT list implementation
Simpler to write
A Summary of Position-Oriented ADTs Position-oriented ADTs
List Stack Queue
Stacks and queues Only the end positions can be accessed
Lists All positions can be accessed
A Summary of Position-Oriented ADTs Stacks and queues are very similar
Operations of stacks and queues can be paired off as
createStack and createQueue Stack isEmpty and queue isEmpty push and enqueue pop and dequeue Stack getTop and queue getFront
A Summary of Position-Oriented ADTs ADT list operations generalize stack and
queue operations– getLength– insert– remove– retrieve
ADT objects
Rely on use of an Abstract Class which contains the referencing mechanism and allows objects to be included in the collections.
ABSTRACT BASE CLASSES
class Object{
public: Object(){;}
virtual ~Object(){;}virtual ostream& printOn(ostream&) const = 0;friend ostream& operator<<(ostream& out,
const Object& ob){
ob.printOn(out);return out;
}}
A linked List
class Entry{
public:
Entry *next;
Object *info;
Entry( Object *obj ) {info = obj; next = 0; }
~Entry() { if( ! (info==0) ) delete info; }
};
Use this as data for linked listclass List
{
private:
Entry *head;
int NoEntries;
public:
List() { head = 0; NoEntries=0;}
~List();
linked list cont.
Entry* returnHead() const { return head ;}
void add( Object& );
int isEmpty(){return head == 0;}
};
Linked list
void List::add( Object& newEntry )
{
Entry *newElement = new Entry( &newEntry );
newElement->next = head;
head = newElement;
NoEntries++;
}
Destructor
List::~List(){while(head != 0){
Entry* temp = head;head = head-> next;delete temp;
}}
Container Class
As can be seen form the previous example the object is a Node which is part of a list
The list is an example of a container class
Container Classes Container classes are an important category of ADTs
They are used to maintain collections of elements like stacks, queues, linked lists, tables,trees, etc.
Container classes form the basis for various C++ class libraries C++ container classes can be implemented using several
methods: Ad hoc, rewrite from scratch each time A generic class facility (eg. list class with list nodes) Parameterised Types (use of templates to generalise the class) void Pointer Method (allows heterogenous collections)
Example Pointer Method
Generic ADT List container class 4 basic operations
Insert Membership (e.g. IsInList) Removal Iteration (e.g. Display routine)
Example ApplicationsGeneric List.h
#ifndef Generic List
#define Generic List
class List {
public:
List (void);
~List (void);
void remove current (void);
// Used as iterators: : :
void reset (void);
void next (void);
protected:
class Node f
friend List;
public:
Node (void *, Node *n = 0);
~Node (void);
void add to front (void *);
void add to end (void *);
Node *remove (void *);
private:
void *element ; // Pointer to actual data
Node *next ;};
Generic List.h (cont'd)
protected:
// used by subclasses for implementation
void add to end (void *);
void add to front (void *);
Node *current value (void);
void *current (void);
bool includes (void *);
void *remove (void *);
// important to make match virtual!
virtual bool match (void *, void *);
private:
Node *head ;
Node *iter ; // used to iterate over lists
};
// Iterator functions
inline List::Node *List::current value (void) {
return this->iter ;
}
inline void List::reset (void) {
this->iter = this->head ;
}
inline void *List::current (void) {
if (this->iter )
return this->iter ->element ;
else
return 0;
}
inline void List::next (void) {
this->iter = this->iter->next ;
}
Class templates Class templates enable reusable data types to
be easily created Often called generic programming
For example we can create a generic stack (a last in first out data structure) using class templates The generic stack can be instantiated with any
data type Stack of integers, stack of doubles, stack of
dates etc
// Stack class template// Stack class templatetemplate <class T> class Stacktemplate <class T> class Stack{{
private:private:int size;int size; // No. of elements in // No. of elements in
the stackthe stackint top;int top; // Location of the top element// Location of the top elementT* stackPtr;T* stackPtr; // Pointer to the stack// Pointer to the stack
public:public:Stack(int);Stack(int);~Stack() { delete[] stackPtr; }~Stack() { delete[] stackPtr; }int push(const T&);int push(const T&); // Push an element// Push an elementint pop(T&);int pop(T&); // Pop an // Pop an
elementelementint isEmpty() { return top==-1;}int isEmpty() { return top==-1;}int isFull() { return top==size-1;}int isFull() { return top==size-1;}
};};
void main()void main(){{
Stack<char> charStack(7);Stack<char> charStack(7);char[] name=“Michael”;char[] name=“Michael”;
int j=0;int j=0;while(charStack.push(name[j])while(charStack.push(name[j])
j++;j++;
char c;char c;cout << “My name in reverse is : “;cout << “My name in reverse is : “;while(charStack.pop(c))while(charStack.pop(c))
cout << c;cout << c;
}}
This code assumes that overloaded assignment operator function exist for programmer defined data types This must be provided if the object used with
the Stack class contains dynamically allocated memory
Template Definition
Cambridge Dictionary template 1 a pattern made of metal, plastic or paper, which is used for making many copies of a shape or to help cut material accurately
2 a system that helps you arrange information on a computer screen
C++ Pattern for handling generic data
Function overloading
Swap revisited To handle integers
void swap(int& rnA, int& rnB){ int nTemp;
nTemp = rnA; rnA = rnB;
rnB = nTemp}
Function overloading
Swap revisited To handle characters
void swap(char& rnA, char& rnB){ char nTemp;
nTemp = rnA; rnA = rnB;
rnB = nTemp}
Function overloading
Swap revisited float, double ……. Separate functions for each ??
Generic function Generic functionality Generic data – automatically typed when used Template function
Template function
Conceptually
void swap(Type_of_Var& Var1, Type_of_Var& Var2){ Type_of_Var Temp; Temp = Var1; Var1 = Var2; Var2 = Temp;}
Template Function - syntax
template<class T> // template prefixvoid swapValues(T& Var1, T& Var2){
T Temp;Temp = Var1;Var1 = Var2;Var2 = Temp;
}
For demonstration see – Template1.cpp
Template functions - array print Handling unspecified arrays Array length?
template<class T>void printArray(const T *array, const int nSize){
for(int nCount = 0; nCount < nSize; nCount++)
cout << array[nCount] << “ “;
cout << endl;}
For usage example see – Template2.cpp
Template Functions - returningAlso possible to have generic return
template<class T>
T addValues(T Val1, T Val2)
{
return Val1 + Val2;
}
See Template3.cpp for usage example
Template Functions – multiple types Possible to have more than one type
template<class T1, class T2> Must use all parameters All must be utilised within function See Template4.cpp
Possible to use Tx for casting and return type See Template5.cpp
Template functions - Plenary
Produce generic solution Data types provided at run time Operators must be able to handle types Overloaded operators included Use of keyword “class” can be replaced with
“typename” ANSI/ISO standard allows Programmers tend to use “class”
Class Templates
Syntax basically the same as when using function templates must use keyword “class”
template<class T>class Pair{private:
T first;T second;
private:Pair();Pair(T Val1, T Val2);
etc….. See Template6.cpp for further details
Class templates
So far….. Class within main file Could place within .h file
and include See Template7.cpp
Shows use of Array of pointers ? – mixed types?
Creating function templates from class templates We can easily create a function template
by passing a class template as an argument to a function A classic example is a sort() function template
which sorts the contents of a container template (for example and array) passed as an argument
We can then create a sort() function template
template<class T> void sort(Vector<T>& v)template<class T> void sort(Vector<T>& v){{
// sort the elements of v into increasing// sort the elements of v into increasing// order using a bubble sort// order using a bubble sort
int size=v.getSize();int size=v.getSize();for (int i=0; i<size-1; i++)for (int i=0; i<size-1; i++)
for (int j=size; i<j; j--)for (int j=size; i<j; j--)if (v[j]<v[j-1])if (v[j]<v[j-1]) // swap v[j] & // swap v[j] &
v[i]v[i]{{
T t = v[j];T t = v[j];v[j]=v[j-1];v[j]=v[j-1];v[j-1] = t;v[j-1] = t;
}}}}
void main()void main(){{
Vector<int>& vi(100);Vector<int>& vi(100);Vector<char*>& vc(100);Vector<char*>& vc(100);Vector<float>& vf(100);Vector<float>& vf(100);Vector<Circle>& vci(100);Vector<Circle>& vci(100);
// initialize the vectors// initialize the vectors// …..// …..
..sort(vi);sort(vi);sort(vc);sort(vc);sort(vf);sort(vf);sort(vci);sort(vci);
}}
The compiler will try and create the correct sort() functions by instantiating the templated functions
It will run into 2 problems in this example Instantiating sort() with a char* (a string) argument will
produce incorrect results The ‘<‘ operator will not test for alphabetical
ordering of the strings Instantiating sort() with a Circle object argument will
produce a compilation error We need an overloaded operator<() function
defined on Circle objects
We can also create an operator<() function for Circle objects
int operator < (Circle& c1,Circel& c2)int operator < (Circle& c1,Circel& c2){{return c1.radius<c2.radius;return c1.radius<c2.radius;}}
Other features of templates
Templates and friends With templates, friendship can be established
between either a class template or a particular instantiation of the template and global/member functions or entire classes
A few examples will clarify this:
Declare a function f() to be a friend of every class specialization of class template X
Declare every member function of class Y to be a friend of every class specialization of class template X
template<class T> class Xtemplate<class T> class X{{
……..friend void f();friend void f();……..
}}
template<class T> class Xtemplate<class T> class X{{
……..friend class Y;friend class Y;……..
}}
The Standard Template Library (STL)
The Standard Template Library (STL) is an addition to the C++ Standard Library
Developed at the Hewlett-Packard Labs in the mid-late 90’s
STL defines powerful, template-based, reuseable components that implement many common data structures and algorithms to process those data structures
STL is extremely complex, being optimised for efficiency.
STL is based on 3 components
Containers
Iterators
Algorithms
Template-based containers are data structures used to group objects of any type
Examples include linked lists, vectors and sets
Iterators encapsulate the mechanisms used to access container elements
A simple pointer can be used as an iterator for a standard array
Algorithms are functions that perform common manipulations on containers
Examples include searching and sorting algorithms There are around 70 algorithms implemented in the
STL A key aspect of the STL is that an algorithm can be applied
to a container without regard to the exact implementation of the container The container’s iterator just has to support the
minimum requirement of the algorithm This means that programmers can write one algorithm
which can be applied to multiple containers
Examples of sequence STL containers include vector
Provides random access with constant time insertions and deletions at the end
deque (double entry queue) Provides random access with constant
time insertions and deletions at the beginning and the end
list Provides linear time access but constant
time insertions and deletions at any position in the list
Examples of associative STL containers include set
Provides rapid lookup (set membership), no duplicates around
multiset As above but allows duplicates
Iterators
Iterators allow generic algorithms to ‘plug in’ to different containers As long as the container supports the iterator
that the algorithm uses to access container elements, the algorithm can be applied to it
There are different classes of iterator to support things like linear or random access
However, certain iterator operations are uniform and can be applied to all containers
* (de-referencing) allows access to the element to pointer to by the iterator
++ (increment) moves the iterator to the next element
begin() points the iterator at the first element
end() points the iterator at the last element
Generally speaking, we have the following sub-division of iterators and associated containers Sequence containers vector, deque
Random access iterators Sequence container list
Linear bidirectional iterator Associative containers set, multi-set, map,
multi-map Linear bidirectional iterator
No iterators supported for stack, queue, priority queue
Iterator operations Depends on iterator type A few examples
++p, p++,--p, p--(pre and post increment/decrement)
Applies to bidirectional and random access *p (de-referencing)
Applies to bidirectional and random access p==p1(test for equality)
Applies to bidirectional and random access
Example. vector
Enables efficient random access rather like an array but can re-size itself
Supports a random access iterator All STL algorithms can operate on a vector as
they all support random access A vector has a size (the actual number of
elements in the container) and a capacity (the number of elements that can be added before the vector resizes)
#include <vector>#include <vector>
int main()int main(){{
int array[6]={1,2,3,4,5,6};int array[6]={1,2,3,4,5,6};
vector<int> vec(array,array+6);vector<int> vec(array,array+6);
for (int *ptr=array; ptr!=(array+6); ptr++)for (int *ptr=array; ptr!=(array+6); ptr++)cout<<*ptr;cout<<*ptr;
vector<T>::iterator it;vector<T>::iterator it;for (it=vec.begin(); it!=vec.end(); it++)for (it=vec.begin(); it!=vec.end(); it++)
cout << *it;cout << *it;
// sort the vector// sort the vectorsort(vec.begin(),vec.end());sort(vec.begin(),vec.end());
}}
The previous program shows the similarity between array access using pointers and container access using an iterator Also de-referening an iterator (pointer) to access the
container (array) element Also the program shows how a sort() function is called
Iterators passed as arguments In general the STL is enormously powerful and should
always be used in preference to custom written container classes