Template Classes and Functions Andy Wang Object Oriented
Template Classes and Functions Andy Wang Object Oriented Programming in C++ COP 3330
Function Templates A function template can perform the same algorithm for different types without specifying the types in advance Example: a function that computes the maximum for three different integers int maximum(int a, int b, int c) { int max = a; if (b > max) max = b; if (c > max) max = c; return max; }
Function Templates However, this function only works for int variables (or types that can be automatically converted to int) What if we wanted to compare variables with the type double? Do we have to write a new function? A function template allows this problem to be solved easily, with only one function
Templated Version of Maximum http: //www. cs. fsu. edu/~myers/deitel 5 c++/ch 06/Fig 06_ 26_27/
maximum. h template<class T> T maximum(T value 1, T value 2, T value 3) { T maximum. Value = value 1; if (value 2 > maximum. Value) maximum. Value = value 2; if (value 3 > maximumvalue) maximum. Value = value 3; return maximum. Value; }
figure 06_27. cpp #include <iostream> #include “maximum. h” using namespace std; int main() { int 1, int 2, int 3; cout << “Input three integer values: “; cin >> int 1 >> int 2 >> int 3; cout << “The maximum integer value is: “; << maximum(int 1, int 2, int 3);
figure 06_27. cpp double 1, double 2, double 3; cout << “nn. Input three double values: “; cin >> double 1 >> double 2 >> double 3; cout << “The maximum double value is: “; << maximum(double 1, double 2, double 3); char 1, char 2, char 3; cout << “nn. Input three characters: “; cin >> char 1 >> char 2 >> char 3; cout << “The maximum character value is: “ << maximum(char 1, char 2, char 3); return 0; }
Another Example http: //www. cs. fsu. edu/~myers/deitel 5 c++/ch 14/Fig 14_ 01/fig 14_01. cpp This is a function template that prints the contents of the array template<class T> void print. Array(const T*array, const int count) { for (int j = 0; j < count; j++) cout << array[j] << “ “; cout << endl; } This function will work on arrays of any class type when an appropriate insertion operator << has been defined
Another Example int main() { const int a. Count = 5; const int b. Count = 7; const int c. Count = 6; int a[a. Count] = {1, 2, 3, 4, 5}; double b[b. Count] = {1. 1, 2. 2, 3. 3, 4. 4, 5. 5, 6. 6, 7. 7}; char c[c. Count] = “HELLO”; cout << “Array a contains: “ << endl; print. Array(a, a. Count); cout << “Array b contains: “ << endl; print. Array(b, b. Count); cout << “Array c contains: “ << endl; print. Array(c, c. Count); return 0; }
Example: Swap http: //www. cs. fsu. edu/~myers/savitch 3 c++/Ch 16/1601. cpp
16 -01. cpp #include <iostream> using namespace std; template<class T> void swap. Values(T &variable 1, T &variable 2) { T temp; temp = variable 1; variable 1 = variable 2; variable 2 = temp; }
16 -01. cpp int main() { integer 1 = 1, integer 2 = 2; cout << “Original integer values are “ << integer 1 << “ “ << integer 2 << endl; swap. Values(integer 1, integer 2); cout << “Swapped integer values are “ << integer 1 << “ “ << integer 2 << endl; char symbol 1 = ‘A’, symbol 2 = ‘B’; cout << "Original character values are: " << symbol 1 << " " << symbol 2 << endl; swap. Values(symbol 1, symbol 2); cout << "Swapped character values are: " << symbol 1 << " " << symbol 2 << endl; return 0; }
Making Container Classes Versatile Here is an example of a class that uses array-based storage to maintain a list of integers http: //www. cs. fsu. edu/~myers/cop 3330/examples/templ ates/simplelist 1/
simplelist 1. h const int MAX = 10; class Simple. List { public: Simple. List() { current = 0; } bool Insert(int item); int Get. Element(unsigned int n); void Print(); int Get. Size() { return current; } private: int array[MAX]; int current; };
simplelist 1. cpp #include <iostream> #include “simplelist 1. h” using namespace std; bool Simple. List: : Insert(int item) { if (current < MAX) { array[current++] = item; return true; } else return false; } int Simple. List: : Get. Element(unsigned int n) { if (n >= MAX) n = MAX – 1; return array[n]; }
simplelist 1. cpp void Simple. List: : Print() { if (current == 0) cout << “Empty List”; return; for (int j = 0; j < current – 1; j++) cout << array[j] << ‘ ‘; cout << array[current - 1]; }
Suppose… We want to have a class that can store a list of double values or a list of characters We could write a similar class for each new type A common C trick is to use a typedef to create a simple user-defined type For example, we can define mytype to be a synonym for the type int typedef int mytype; We can also define mytype as double typedef double mytype;
By doing so… We can define a class using mytype To change an int array to a double array, just change the typedef for mytype, and recompile http: //www. cs. fsu. edu/~myers/cop 3330/examples/tem plates/simplelist 2/
simplelist 2. h const int MAX = 10; typedef int mytype; class Simple. List { public: Simple. List() { current = 0; } bool Insert(mytype item); mytype Get. Element(unsigned int n); void Print(); int Get. Size() { return current; } private: mytype array[MAX]; int current; };
simplelist 2. cpp #include <iostream> #include "simplelist 2. h" using namespace std; bool Simple. List: : Insert(mytype item) { if (current < MAX) { array[current++] = item; return true; } else return false; } mytype Simple. List: : Get. Element(unsigned int n) { if (n >= MAX) n = MAX - 1; return array[n]; }
simplelist 2. cpp void Simple. List: : Print() { if (current == 0) { cout << "Empty List"; return; } for (int i = 0; i < current - 1; i++) cout << array[i] << ' '; cout << array[current - 1]; }
Class Templates With class templates, we can make this class work with different types without altering and recompiling the code To make a class into a template, prefix the class definition with the syntax template<class T> T is a type parameter, and it can have any name When the class is instantiated, we fill in an appropriate type Use the same prefix on the definitions of the member functions
Class Templates For member functions, the name of the class will be class. Name<T>: : member. Name In the Simple. List example, the type of the array is T, which will be filled in when an object is created Also, in the main program, we must #include the actual definition file, in addition to the class declaration The compiler creates a different version of the class for each type that is used Thus, either the entire class should be written in the header file, OR the. cpp file should be #included #include “simplelist 3. cpp”
Simple. List Class Template Example http: //www. cs. fsu. edu/~myers/cop 3330/examples/tem plates/simplelist 3/
simplelist 3. h const int MAX = 10; template<class T> class Simple. List { public: Simple. List() { current = 0; } bool Insert(T item); T Get. Element(unsigned int n); void Print(); int Get. Size() { return current; } private: T array[MAX]; int current; };
simplelist 3. cpp #include <iostream> #include "simplelist 3. h" using namespace std; #ifndef _SIMPLELIST_CPP #define _SIMPLELIST_CPP template<class T> bool Simple. List<T>: : Insert(T item) { if (current < MAX) { array[current++] = item; return true; } else return false; }
simplelist 3. cpp template<class T> T Simple. List<T>: : Get. Element(unsigned int n) { if (n >= MAX) n = MAX - 1; return array[n]; } template<class T> void Simple. List<T>: : Print() { if (current == 0) { cout << "Empty List"; return; } for (int i = 0; i < current-1; i++) cout << array[i] << ' '; cout << array[current - 1]; } #endif
main. cpp #include <iostream> #include “simplelist 3. cpp” using namespace std; int main() { Simpe. List<int> list 1; for (int j = 0; j < 8; j++) list 1. Insert(i*3); cout << “Element at index 4 = “ << list 1. Get. Element(4) << endl; cout << “Entire list is: n”; list 1. Print(); cout << “nn”;
main. cpp Simple. List<double> list 2; for (int j = 0; j < 10; j++) list 2. Insert(j * 1. 1); cout << “Element at index 6 = “ << list 2. Get. Element(6) << endl; cout << “Entire list is: n”; list 2. Print(); cout << “nn”; return 0; }
Dynamic List Example http: //www. cs. fsu. edu/~myers/cop 3330/examples/tem plates/tlist/
tlist. h #include <iostream> Using namespace std; #ifndef _LIST_H #define _LIST_H template<class T> class List { public: List(int s = 10); ~List(); List(const List<T> &); List &operator=(const List<T> &); void Insert(T item); T Get. Element(unsigned int n); void Print(ostream &os);
tlist. h private: T* data; int size, max; void Clone(const List<T> &); void Resize(int newsize); }; template<class T> List<T>: : List(int s) { size = 0; max = s; if (max <= 0) { data = 0; max = 0; } else data = new T[max]; }
tlist. h template<class T> List<T>: : ~List() { if (data) delete [] data; } template<class T> List<T>: : List(const List<T> &L) { Clone(L); } template<class T> List<T> &List<T>: : operator=(const List<T> &L) { if (this != &L) { if (data) delete [] data; Clone(L); } return *this; }
tlist. h template<class T> void List<T>: : Insert(T item) { if (max == size) Resize(max + 5); data[size] = item; size++; } template<class T> T List<T>: : Get. Element(unsigned int n) { if (n >= size) n = size – 1; return data[n]; } template<class T> void List<T>: : Print(ostream &os) { if (size == 0) os << “List empty”; for (int j = 0; j < size – 1; j++) os << data[j] << “, “; os << data[size - 1]; }
tlist. h template<class T> void List<T>: : Resize(int newsize) { max = newsize; T *temp = new T[max]; for (int j = 0; j < size; j++) temp[j] = data[j]; if (data != 0) delete [] data; data = temp; } template<class T> void List<T>: : Clone(const List<T> &L) { max = L. max; size = L. size; date = new T[max]; for (int j = 0; j < size; j++) data[j] = L. data[j]; }
main. cpp #include <iostream> #include “tlist. h” using namespace std; int main() { List<int> tests; int gr; cout << “Enter some grades (negative to quite): n “; do { cin >> gr; if (gr >= 0) tests. Insert(gr); } while (gr >= 0); cout << “The 7 th element is: “ << test. Get. Element(7) << endl; cout << “The 2 nd element is: “ << test. Get. Element(2) << endl;
main. cpp cout << “Here is the list of grades: nn”; test. Print(); cout << “nn. Creating a list of doublesn”; List<double> stats(0); double num; cout << “Enter some floating point numbers (negative to quitn”; do { cin >> num; if (num >= 0) stats. Insert(num); } while (num >= 0);
main. cpp cout << "The 6 th element is: " << stats. Get. Element(6) << 'n'; cout << "The 2 nd element is: " << stats. Get. Element(2) << 'n'; cout << "Here is the list of doubles: nn"; stats. Print(cout); cout << "nn"; return 0; }
main 2. cpp #include <iostream> #include <string> #include “tlist. h” using namespace std; template<class T> void Test. List(List<T> the. List, string label, int val 1, int val 2) { T gr; cout << “Enter some “ << label << “ (negative to quite): n “; do { cin >> gr; if (gr >= 0) the. List. Insert(gr); } while (gr >= 0)
main 2. cpp cout << "Element " << val 1 << " is: " << the. List. Get. Element(val 1) << 'n'; cout << "Element " << val 2 << " is: " << the. List. Get. Element(val 2) << 'n'; cout << "Here is the list of " << label << ": nn"; the. List. Print(cout); } int main() { List<int> tests; List<double> stats(0); Test. List(tests, "grades", 7, 2); Test. List(stats, "floats", 6, 2); }
- Slides: 40