330 likes | 395 Views
Lecture 5. OOP Course. 5. Templates. Motivation. A function for finding minimum value For floats we will need another function Can we parameterize this function with a type ? Towards Generic Programming
E N D
Lecture 5 OOP Course
Motivation • A function for finding minimum value • For floats we will need another function • Can we parameterize this function with a type? • Towards Generic Programming • Like objects are generalized into classes, we would like to generalize classes and functions intotemplates • int min(int a, int b){ • return (a<b ? a : b) • } • float min(float a, float b){ • return (a<b ? a : b) • }
Motivation void swap(int& a, int& b){ int temp = a; a = b; b = temp; } void swap(short& a, short& b){ short temp = a; a = b; b = temp; } void swap(string& a, string& b){ string temp = a; a = b; b = temp; } void swap(Elephant& a, Elephant& b){ Elephant temp = a; a = b; b = temp; } void swap(Parrot& a, Parrot& b){ Parrot temp = a; a = b; b = temp; } void swap(char& a, char& b){ char temp = a; a = b; b = temp; } void swap(boolean& a, boolean& b){ boolean temp = a; a = b; b = temp; } void swap(Eagle& a, Eagle& b){ Eagle temp = a; a = b; b = temp; } void swap(Snake& a, Snake& b){ Snake temp = a; a = b; b = temp; } void swap(Cat& a, Cat& b){ Cat temp = a; a = b; b = temp; } void swap(double& a, double& b){ double temp = a; a = b; b = temp; } void swap(Crocodile& a, Crocodile& b){ Crocodile temp = a; a = b; b = temp; } void swap(float& a, float& b){ float temp = a; a = b; b = temp; }
Templates • C++ provides a super macro mechanism that is identified by the keyword template • Templates can be thought of as MACROs for functions and classes, that need not be explicitly called by the programmer • Templates are controlled by the compiler (and not by the pre-processor) • Templates arguments are either class-types or const-expressions of a fixed type • Arguments that are passed to temple functions are checked for type-mismatch
Function Template • Preserving the semantics of a function • Automatically generated instance of a function, varying by type • The programmer parameterizes all or a subset of the types in the interface • The function implementation remains invariant over a set of function instances, each handling a unique data type template <class Type> Type min(Type a, Type b) { return ( a>b ? a : b); }
Function Temples Cont. Declaration • Template <calssT> • T min(T a, T b){ • return (a<b ? a : b) • } operator< should be defined for calss T Usage • int main() • { int a=3, b=4; • char c= ‘a’, d = ‘b’; • cout << min(a,b); // o.k • cout << min(c,d); // o.k • cout << min(a,c); // Error!! • return 0; Defining additional function int min(int, int) Will prevent the compilation error
Function Temples Cont. • For each call to a function template, the compiler will try to generate an actual function with the appropriate prototype • Overloading for function of the same name is done in this order: • Look for an exact match among non-template functions • Look for an exact match that can be generated from function template • Look for the best match non-template functions, using • Trivial conversion • Promotions (e.g. short to int) • Standard conversions (e.g. int to double) • User-defined conversions (e.g. double to complex)
Class Templates • Class templates are used to define generic classes • An actual class is created only when an actual object defined, using the class template with actual parameters templete<class E, int size> class Buffer; Buffer<char*, 1024> buf_chrp; Buffer<int, 1024> buf_int;
Example: class Bag • add • getOne • isEmpty • isFull • currentSize • capacity
Bags With and Without Templates • Differences between .template, .cpp files: • Occurrences of BagOfInt :: are replaced by Bag<Item> :: • Member functions, constructors, destructor are preceded by template<class Item> • Constructors are Bag; destructor is ~Bag • Assumption:Item is a class • See use of NULL in add, getOne
Instantiating Bag Objects Bag<int> bag(40); // locally allocated bag for 40 ptrs to int Bag<int> *bagPtr = new Bag<int>(60); // bagPtr holds the address of a dynamically // allocated bag that stores up to 60 pointers to int Bag< Bag<int> > x(25); // locally allocated. bag x can hold 25 pointers to // bags, each of which can hold pointers to int Bag< Bag<int > > *y = new Bag< Bag<int > > (30); // y holds the address of a dynamically allocated bag // that stores up to 30 pointers to bags of pointers // to int
Instantiating Bag Objects • When Bag<Bag<int>> *y = new Bag<Bag<int>>(30); is first encountered: • First, the class Bag<int> is instantiated • Then the class Bag<Bag<int>> is instantiated • Then the object y is instantiated • When Bag<int> and Bag<Bag<int>> are encountered subsequently, the classes already exist
Operations on OrderedList Assuming we already have the class List<Item>, orderedList<Item> will use List<Item> to store the elements in a sorted order
OrderedList.h #include “List.h” template <class Item> class OrderedList { public: OrderedList(unsigned int capacity = MAX_LIST); // constructor for an empty ordered list that // can hold up to capacity items; default // size is defined in List.h ~OrderedList( ); // destructor bool isEmpty( ) const; // true if list is empty, false otherwise
OrderedList.h int getLength( ) const; // returns the current size of the list Item remove (unsignedint pos); // remove the value at location pos and return it // precondition: pos must be a legal list position Item retrieve (unsignedint pos) const; // return value at pos without modifying the list. // precondition: pos must be a legal list position // cont’d..
OrderedList.h void insert (Item item); // insert item at appropriate pos’n in list int find (Item item) const; // return pos’n of first occurrence of // item, or -1 if item isn’t found private: List<Item> m_container; // to hold the list of Items }; // end of header file
OrderedList.template #include <stdlib.h> template <class Item> OrderedList<Item> :: OrderedList (unsignedint capacity ) : m_container(capacity) { } template <class Item> OrderedList<Item> :: ~OrderedList ( ) { } // cont’d..
OrderedList.template template <class Item> bool OrderedList<Item> :: isEmpty( ) const { return m_container.isEmpty( ); } template <class Item> int OrderedList<Item> :: getLength( ) const { return m_container.getLength( ); } // cont’d..
OrderedList.template template <class Item> Item OrderedList<Item> :: remove (unsignedint pos) { return m_container.remove(pos); } template <class Item> Item OrderedList<Item> :: retrieve (unsignedint pos) const { return m_container.retrieve(pos); } // cont’d..
OrderedList.template template <class Item> void OrderedList<Item> :: insert (Item item) { for ( int k = 1; k <= getLength( ); k++ ) if ( item < retrieve(k) ) break; m_container.insert( k, item ); }// cont’d..
OrderedList.template template <class Item> int OrderedList<Item> :: find (Item item) const { for ( int k=1; k <= getLength( ); k++ ) if ( item == retrieve(k) ) return k; return –1; } // end of OrderedList implementation Next lecture: we will see a better way to implement OrederedList<Item>, using Inheritance