1 / 20

CSC 237 - Data Structures, Fall, 2008

CSC 237 - Data Structures, Fall, 2008. Monday, September 29, end of week 5, Generic Functions and Classes in C++. Fixed types in containers. Fixed types in containers present a problem Containers can contain only 1 kind of application value.

damia
Download Presentation

CSC 237 - Data Structures, Fall, 2008

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

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 <typename ElemType> 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 <<interface>> sequence_interface sequence_stl_vectorimpl insert(), remove() get(), size() private: vector<string *> stringVector ; // Store and retrieve from here. vector<bool> deleteVector ; // isDeleteLater flags vector does conceptual array expansion/contraction for you.

  12. basic vector and vector::iterator indexing operations • int count = stringVector.size(); • vector<string *>::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 randomiterator

  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.

More Related