Presentation is loading. Please wait.

Presentation is loading. Please wait.

CSC 237 - Data Structures, Fall, 2008 Monday, September 29, end of week 5, Generic Functions and Classes in C++

Similar presentations


Presentation on theme: "CSC 237 - Data Structures, Fall, 2008 Monday, September 29, end of week 5, Generic Functions and Classes in C++"— Presentation transcript:

1 CSC 237 - Data Structures, Fall, 2008 Monday, September 29, end of week 5, Generic Functions and Classes in C++

2 Fixed types in containers Fixed types in containers present a problem Containers can contain only 1 kind of application value. You cannot use a linked list of strings to store a sequence of ints or other application types. class sequence_linkedlistimpl : public sequence_interface { … struct listelement { // private local helper class string *content ; bool deleteFlag ; listelement *next } *first ; int count ; }

3 Void *’s are an old, unsafe solution Unknown types present a different problem (void *) cast when storing a pointer is safe. How about casting from a (void *) to another pointer type when retrieving data? class sequence_linkedlistimpl : public sequence_interface { … struct listelement { // private local helper class void *content ; bool deleteFlag ; listelement *next } *first ; int count ; }

4 C++ templates for generic functions and templates Suppose you want to define a linked list or other container class that can contain different data types when used by different client modules. sequence of “string *” as in our current assignment sequence of “int” or “double” for another application sequence of other C++ object types You may also want to do this for functions sum() to add integers or to concatenate strings

5 Templates have variables for types A C++ template makes one or more types into variables when writing a library function or class. You can write a single library that works with different client types for different client “calls” to that library. Each client call to the library binds the template type variable to a fixed type. Templates allow you to reuse an algorithm or class without rewriting type-dependent code.

6 Example: a function that sums different types of parameters The recursive bisection algorithm of the last assignment could sum integers, sum doubles precision floats, concatenate strings,... int sum(int count, int iarray[]) { if (count == 0) { return 0 ; } else if (count == 1) { return iarray[0] ; } else { int midpoint = count / 2 ; return sum(midpoint, iarray) + sum(count-midpoint, iarray+midpoint);}}

7 Use an ElemType array, where ElemType varies template ElemType sum(int count, ElemType values[], ElemType nullvalue) { ElemType result ; if (count == 0) { result = nullvalue ; } else if (count == 1) { result = iarray[0] ; } else { int midpoint = count / 2 ; result = sum(midpoint, iarray, nullvalue) + sum(count-midpoint, iarray+midpoint, nullvalue); } return result ; }

8 Client code binds ElemType when the client code compiles ~parson/DataStructures/template_sum: int *intarray = new int [ argc-1 ]; double *dblarray = new double [ argc-1 ]; string *strarray = new string [ argc-1 ]; int isum = sum(argc-1, intarray, 0); double dsum = sum(argc-1, dblarray, 0.0); static const string nullstring(""); string strsum = sum(argc-1, strarray, nullstring);

9 Standard Template Library The C++ Standard Template Library (STL) provides a set of template classes and functions for supporting access to structured data, along with support for common basic tasks. Containers such as sets, vectors, lists, and tables Iterators are adjunct classes to Containers that allow client code to step through a Container’s contents – they act like pointers, but do not violate encapsulation Algorithms and function objects such as sorting

10 STL References http://www.cplusplus.com/ http://www.cppreference.com/ http://www.sgi.com/tech/stl/ Accessible from my CSC237 course page Containers and iterators come in several abstract flavors input_iterator, output_iterator, forward_iterator, bidirectional_iterator, random_iterator, reverse_iterator and compatible Container types

11 STL-based vector implementation of sequence_interface > sequence_interface sequence_stl_vectorimpl insert(), remove() get(), size() private: vector stringVector ; // Store and retrieve from here. vector deleteVector ; // isDeleteLater flags vector does conceptual array expansion/contraction for you.

12 basic vector and vector::iterator indexing operations int count = stringVector.size(); vector ::iterator stringIterator = stringVector.begin(); // acts like a pointer advance(stringIterator, 1); // stringIterator++ ; stringIterator += realoff ; // advance(stringIterator, realoff) while (stringIterator != stringVector.end())

13 vector and vector::iterator access and mutation operations *stringIterator accesses or modifies the element at which stringIterator “points” stringVector.insert(stringIterator, value); stringVector.erase(stringIterator); string * result = stringVector.at(realoff); vector::iterator is a random iterator

14 STL list and slist slist is STL’s equivalent of our singly-linked list; list is doubly-linked slist uses a forward iterator, while list uses a bidirectional iterator begin() and end() return iterators to the beginning and end, as with other Containers Forward iterator supports ++ operation, and bidirectional iterator adds -- operation

15 Tail recursive definitions of a List List := Node | Node List What problem results from this definition? What kind of List can you NOT represent? How might you fix this problem? Hint: Restate above as List := [Node] | [Node] + List List :=

16 Disadvantages of exposing implementation to client code Suppose you give client code direct access to the struct listelement linked list, so that any client pointer to a listelement is a sequence. How must you implement negative offsets and test non-negative offsets for validity? contents next contents next contents next start of a list start of a different list

17 Advantages of information hiding and data abstraction contents next contents next contents next start of the list (first), count of nodes Abstracting the sequence and hiding the linked list lets you use count to determine offset validity without searching the list. You can still provide client code with the advantages of recursive lists by creating operations to clone sub- sequences. Private operations can manipulate nodes directly.

18 Implementation alternatives “Partitioning the design space” contents next contents next contents next start of the list (first), count of nodes Suppose you want to define member operation virtual sequence_interface *clone(int offset) that copies a subsequence into a new object. Should you copy list nodes or create new ones? How might you deal with node and string deletion in one linked list and not the other?

19 Implementation alternatives “Optimizing common use cases” contents next contents next contents next start of the list (first), count of nodes Suppose a majority of client code accesses comprise a series of get(offset) invocations, where offset is 0, 1, 2,..., n-1. What can you do to accelerate this typical usage? Why is information hiding useful in this case? Do insert() or remove() create any hurdles?

20 Circular sequences Circular arrays use modulo addition for indices index = (index + 1) % arraySize index = (index – 1 + arraySize) % arraySize Circular linked lists point from the last to the first element Doubly linked lists link the list head and tail together in both directions They are especially useful for queues, also know as first-in first-out (FIFO) sequences.


Download ppt "CSC 237 - Data Structures, Fall, 2008 Monday, September 29, end of week 5, Generic Functions and Classes in C++"

Similar presentations


Ads by Google