Function and Class Templates A R Hadaegh Dr

  • Slides: 26
Download presentation
Function and Class Templates A. R. Hadaegh Dr. Ahmad R. Hadaegh California State University

Function and Class Templates A. R. Hadaegh Dr. Ahmad R. Hadaegh California State University San Marcos (CSUSM) Page 1

Introduction - Template enables us to specify with a single code segment, an entire

Introduction - Template enables us to specify with a single code segment, an entire range of related functions called template functions or an entire range of related classes called template classes - For example, we can write a single function template for an array that - sorts an array of integers - sorts an array of doubles - or even an array of a complex type such as employee class A. R. Hadaegh Dr. Ahmad R. Hadaegh California State University San Marcos (CSUSM) Page 2

Function Template - Suppose we want to write a function that prints the contents

Function Template - Suppose we want to write a function that prints the contents of an array. - If this array is an array of integers, a possible implementation can be as follows: void print. Array (int array[], int array. Size) { for (int i=0; i<array. Size; i++) cout << array[i] << “ ”; } - where array is the name of the array and array. Size refers to the size of the array. A. R. Hadaegh Dr. Ahmad R. Hadaegh California State University San Marcos (CSUSM) Page 3

- Note that the prototype of this function can be written as: void print.

- Note that the prototype of this function can be written as: void print. Array(int[], int); - Can we call the above function to print other types of arrays such as an array of double, or an an array of char, or an array of class employee, and so on? - The answer is that with Traditional C language, this is not possible. However, with object-oriented tools it is possible. A. R. Hadaegh Dr. Ahmad R. Hadaegh California State University San Marcos (CSUSM) Page 4

- In traditional C, we need to take care of two issues: - First,

- In traditional C, we need to take care of two issues: - First, we need to have a separate print function, one for each type of the array we use in our program - Second, if all of these arrays are under one project (program) their names must be different. - we cannot have two function of the same name in Traditional C language - For example, if we have three arrays of types int, char, double, we may need to have three functions such as: void print. Int. Array(int[], int); void print. Double. Array(double[], int); void print. Char. Array(char[], int); A. R. Hadaegh Dr. Ahmad R. Hadaegh California State University San Marcos (CSUSM) Page 5

Overloading the functions - Remember the concept of overloading in C++. - In C++,

Overloading the functions - Remember the concept of overloading in C++. - In C++, we can overload the functions. This means, we can have several functions with the same name but different signature (their return type and/or parameters have different types, or number of parameters can be different). - If we overload our print. Array function we can have three functions one for each different type but all with the same name. void print. Array(int[], int); void print. Array(double[], int); void print. Array(char[], int); A. R. Hadaegh Dr. Ahmad R. Hadaegh California State University San Marcos (CSUSM) Page 6

Using function Template - With overloading, we do not need to give each function

Using function Template - With overloading, we do not need to give each function a distinct name; however, we still need to have one function for each type of the array. - If we use a template function, to print the array, we only need to write one function to take care of any form of array. - Based on the argument types provided explicitly or inferred from calls to the template function, the compiler generates separate object-code functions to handle each type of call appropriately. A. R. Hadaegh Dr. Ahmad R. Hadaegh California State University San Marcos (CSUSM) Page 7

Syntax - for our print. Array function, the syntax is as follows: template<class T>

Syntax - for our print. Array function, the syntax is as follows: template<class T> void print. Array (T array[], int array. Size) { for (int i=0; i<array. Size; i++) cout << array[i] << “ ”; } - All function template definitions begin with the keyword template followed by a list of formal type parameters to the function template enclosed in angle bracket (< >) - Each formal type parameter must be proceeded by the keyword class or a typename A. R. Hadaegh Dr. Ahmad R. Hadaegh California State University San Marcos (CSUSM) Page 8

- You can have more than one array to be printed template<class T 1,

- You can have more than one array to be printed template<class T 1, class T 2> void print. Array(const T 1 array 1[], int count 1, const T 2 array 2[], int count 2) { for (int i=0; i<count 1; i++) cout << array 1[i] << " "; cout << endl; for (i=0; i<count 2; i++) cout << array 2[i] << " "; cout << endl; } void main() { const int a. Count =5, c. Count = 12; int a[a. Count] = {1, 2, 3, 4, 5}; char c[c. Count] = "HELLO THERE"; print. Array(a, a. Count, c, c. Count); } <See Example 1> A. R. Hadaegh Dr. Ahmad R. Hadaegh California State University San Marcos (CSUSM) Page 9

Class Template - Class template are called parameterized types because they require one or

Class Template - Class template are called parameterized types because they require one or more type parameter to specify how to customize a “generic class” template to form a specific template class - As an example, remember about the stack data structure with the first in last out feature - Stack can be of any data type. We can have a stack of integers, a stack of doubles, a stack of Employee class or stack of Student class. - The following is a typical declaration of a stack class including the implementation of the methods <See Example 2> A. R. Hadaegh Dr. Ahmad R. Hadaegh California State University San Marcos (CSUSM) Page 10

class Stack { public: Stack(); bool push(const int&); bool pop(int&); private: int size; int

class Stack { public: Stack(); bool push(const int&); bool pop(int&); private: int size; int top; int stk[3]; }; Stack: : Stack() { size = 3; top = -1; } A. R. Hadaegh Dr. Ahmad R. Hadaegh bool Stack: : pop(int& pop. Value) { if (top>=0) { pop. Value = stk[top]; top--; return true; } return false; } bool Stack: : push(const int& push. Value) { if (top+1 < size) { top++; stk[top] = push. Value; return true; } return false; } California State University San Marcos (CSUSM) Page 11

What is the limitations of our Stack class? - One of the limitation of

What is the limitations of our Stack class? - One of the limitation of our stack class is that all objects of the type Stack class must be integer stack. - What about objects of type stack of doubles or stack of chars, or even more complex classes such as stack of Employees or stack of Students? - One solution is to create one stack class for each desirable type. For example, one for stack of char, another for stack of int, another for stack of double and so on. - This is not a feasible solution because we need to create a new class every time we need a stack of a new type. A. R. Hadaegh Dr. Ahmad R. Hadaegh California State University San Marcos (CSUSM) Page 12

Using template class - Another solution is to use template class. - If we

Using template class - Another solution is to use template class. - If we make the stack to be a class template, our stack class become the basis for creating many stacks classes such as stacks of int, stacks of double, and so on. - The next slide shows how to modify our Stack class to become a class template for any type of Stack class. A. R. Hadaegh Dr. Ahmad R. Hadaegh California State University San Marcos (CSUSM) Page 13

template<class T> class Stack { public: Stack(); bool push(const T&); bool pop(T&); private: int

template<class T> class Stack { public: Stack(); bool push(const T&); bool pop(T&); private: int size; int top; T stk[3]; }; template <class T> Stack<T>: : Stack() { size = 3; top = -1; } A. R. Hadaegh Dr. Ahmad R. Hadaegh template <class T> bool Stack<T>: : pop(T& pop. Value) { if (top>=0) { pop. Value = stk[top]; top--; return true; } return false; } template <class T> bool Stack<T>: : push(const T& push. Value) { if (top+1 < size) { top++; stk[top] = push. Value; return true; } return false; } California State University San Marcos (CSUSM) Page 14

- In general to produce a variety of template classes, we simply need to

- In general to produce a variety of template classes, we simply need to write one class template definition. - Each time we need a new type specific instantiation, we can declare the associated object and the compiler writes the source-code for the template class we require. - In the main program, we now can use the same class to create two different types of stacks void main() { Stack<double> double. Stack; Stack<int> int. Stack; …. } <See Example 3> A. R. Hadaegh Dr. Ahmad R. Hadaegh California State University San Marcos (CSUSM) Page 15

- Note that each member function definition outside the class begins with the header

- Note that each member function definition outside the class begins with the header template <class T> - The binary scope resolution operator is used with the class template name Stack<T> to tie the member function definition to the class template's scope A. R. Hadaegh Dr. Ahmad R. Hadaegh California State University San Marcos (CSUSM) Page 16

- One of the limitations of the previous example is that all stacks have

- One of the limitations of the previous example is that all stacks have one size, size 3 - We can slightly change our implementation to be able to instantiate stacks of different sizes with different types - In the previous example, the stack class template section used only one type parameter in the template header - It is also possible to use non-type parameters. - For example, the template header in the previous example can be modified to take a non-type parameter as follows: template <class T, int elements> A. R. Hadaegh Dr. Ahmad R. Hadaegh California State University San Marcos (CSUSM) Page 17

- Then a declaration such as Stack <double, 100> my. Stack would instantiate a

- Then a declaration such as Stack <double, 100> my. Stack would instantiate a stack of double with the capacity of 100 elements. - the complete class header and the implementations of the methods are shown in the next slide <See Example 4> A. R. Hadaegh Dr. Ahmad R. Hadaegh California State University San Marcos (CSUSM) Page 18

template<class T, int elements> class Stack {public: Stack(); bool push(const T&); bool pop(T&); private:

template<class T, int elements> class Stack {public: Stack(); bool push(const T&); bool pop(T&); private: int size; int top; T stk[elements]; }; template <class T, int elements> bool Stack<T, elements>: : pop(T& pop. Value) { if (top>=0) { pop. Value = stk[top]; top--; return true; } return false; } template <class T, int elements> bool Stack<T, elements>: : push(const T& push. Value Stack<T, elements>: : Stack() { { if (top+1 < size) size = elements; { top++; top = -1; stk[top] = push. Value; } return true; } return false; } A. R. Hadaegh Dr. Ahmad R. Hadaegh California State University San Marcos (CSUSM) Page 19

template <class T> class Node { public: T object; Node<T> *next; }; template <class

template <class T> class Node { public: T object; Node<T> *next; }; template <class T> LL<T>: : LL() { top = NULL; } template <class T> void LL<T>: : insert. LL (T value) { Node<T> *New. Node; New. Node = new (Node<T>); New. Node->next = top; New. Node->object = value; top = New. Node; } template <class T> class LL LL<T>: : ~LL() { private: { template <class T> Node<T> *top; Node<T> *curr = top, *p; void LL<T>: : print. LL() { Node<T> *curr; public: LL(); while (curr!= NULL) cout << endl; ~LL(); { p = curr; curr = top; void insert. LL(T); curr = curr->next; while (curr != NULL) { void print. LL(T); delete p; cout << curr->object << "->"; }; } curr = curr->next; top = NULL; } } cout << endl; } <See Example 5> A. R. Hadaegh Dr. Ahmad R. Hadaegh California State University San Marcos (CSUSM) Page 20

int main () { LL<int> list 1; list 1. insert. LL(10); list 1. insert.

int main () { LL<int> list 1; list 1. insert. LL(10); list 1. insert. LL(20); list 1. insert. LL(30); cout << "----------------" << endl; list 1. print. LL(); LL<string> list 2; list 2. insert. LL("test"); list 2. insert. LL("a"); list 2. insert. LL("is"); list 2. insert. LL("This"); cout << "----------------" << endl; list 2. print. LL(); } A. R. Hadaegh Dr. Ahmad R. Hadaegh return 0; California State University San Marcos (CSUSM) Page 21

Class template and Template Classes - Template classes of a class template are the

Class template and Template Classes - Template classes of a class template are the set of classes generated at run time for that class template - For example, in our example, for the class template stack, we may create three different objects like: Stack <double, 10> Stack <int, 20> Stack <char, 30> double. Stack int. Stack char. Stack - Instantiation of objects double. Stack, char. Stack, and int. Stack causes the following classes be generated: A. R. Hadaegh Dr. Ahmad R. Hadaegh California State University San Marcos (CSUSM) Page 22

class Stack {public: Stack(); bool push(const int&); bool pop(int &); private: int size; int

class Stack {public: Stack(); bool push(const int&); bool pop(int &); private: int size; int top; int stk[20]; }; class Stack {public: Stack(); bool push(const char&); bool pop(char &); private: int size; int top; char stk[30]; }; class Stack {public: Stack(); bool push(const double&); bool pop(double &); private: int size; int top; double stk[10]; }; A. R. Hadaegh Dr. Ahmad R. Hadaegh California State University San Marcos (CSUSM) Page 23

Templates and Inheritance - A class template can be derived from a template class

Templates and Inheritance - A class template can be derived from a template class - A class template can be derived from a non-template class - A template class can be derived from a class template - A non-template class can be derived from a class template A. R. Hadaegh Dr. Ahmad R. Hadaegh California State University San Marcos (CSUSM) Page 24

Template and friends function - Inside a class template for class X that has

Template and friends function - Inside a class template for class X that has been declared with template <class T > class X - a friend declaration of the form friend void f 1(); makes the stand-alone function f 1() a friend of every template class instantiated from the preceding class template - a friend declaration of the form friend void A: : f 1(); makes method f 1() of class A a friend of every template class instantiated from the preceding class template - a friend declaration of the form friend class Y makes every method of class Y a friend of every template class instantiated from the preceding class template A. R. Hadaegh Dr. Ahmad R. Hadaegh California State University San Marcos (CSUSM) Page 25

Template and friends function - Inside a class template for class X that has

Template and friends function - Inside a class template for class X that has been declared with template <class T > class X - a friend declaration of the form friend void f 2(X<T>&); for a particular type T such as float makes function f 2(X<float>&) a friend of X<float> only - Or a friendship declaration of the form friend class Z<T> when a template class is instantiated with a particular type for T such as float, all members of class Z<float> become friends of template class X<float>. A. R. Hadaegh Dr. Ahmad R. Hadaegh California State University San Marcos (CSUSM) Page 26