At the end of this chapter, you should be able to understand
Using template classes employing template class member functions as well as non-template class member functions.
Use type-specific friend functions and static member function and data.
Use generic programs extensively for data structure implementation such as stack.
Appreciate concepts of developing template libraries.
Generic programming means writing programs that will work for any type of data, i.e. make the programs independent of the type of data. With generic programs, there will be no need to develop type-specific programs for each data type. Templates in C++ are implementation tools provided to write generic programs. For example, a data structure such as stack can be used for storing different types of data such as integers, floats, characters and strings of messages. Using template facility provided by the C++ language, a generic program can be written and stored in a directory and can be used by all programmers for different data types.
Template is a tool provided by C++ for achieving reusability of code. We can hence say that it is a productivity enhancement tool for the programmer. On many occasions, we come across problems in real life wherein the logic is the same but the data set is different. Suppose that we need a function to sort the given data. The data could be data of integers or data of floats or data of double. Do we write separate functions for each of the data types or is there a tool or method wherein one function takes care of all the data types. Function template is the solution provided by C++.
When we consider the array data structure, do we need to write separate classes for each type of array objects such as array of Students, array of cars, or array of Employees? Class template allows us to write a single class template program and allow us to instantiate several arrays of different groups of objects. Therefore, we can conclude that C++ allows data types to be forwarded to function and class definition at run-time as parameters.
Suppose that we implement a stack – a last-in-first-out data structure – to store integers. Then we have modified through cut and paste strategy and implemented a stack of floats. Now if we need stack of orders, what shall we do? Keep copying through cut paste! This is not reusability promised by C++. Class templates are very useful when the logic is the same and data sets are different. For example, if we have a class template for Stack class, we can store integers, floats, objects of students on to Stack. Similarly, an array expressed as template allows us to store an array of integers or an array of students, etc. The main advantage of template classes is that if you declare a class template, you can store it in a directory and use these definitions of class templates as and when required in program development, just by creating instances of objects as and when required. It is precisely this concept of reusability that is of immense value to developers. This aspect will be studied in more detail in the next chapter on standard template libraries.
Stack is the most widely used-user defined structure in problem solving. C++ templates allow us to implement a generic Stack<T> template that has a type parameter T. T can be replaced with actual types at run-time, for example, Stack<int>, and C++ will generate the class Stack<int>. We can also create classes such as Stack<float>, Stack<Student> and Stack<char>. Define template once and use it to create classes of different intrinsic and user-defined data types. Incorporating changes is very easy since once the changes are implemented in the template Stack<T>, they are immediately reflected in all classes – Stack<float>, Stack<Student> and Stack<char>. Our next example amplifies these important concepts.
Example 14.1: Template Class – Stack
A class template definition is just like a regular class definition. It is preceded by the keyword template. For example, here is the definition of a class template for Stack. Note that T is a parameter value which changes with each instance of class we create. The word class is a keyword that specifies that T is a parameter that will be used to represent the parameter type (T). We can create instances of int, float and Students in the void main section as follows:
Stack<int> I; //Stack of integers
Stack<float> F; //Stack of floats
Stack<Student> stdStack; // Stack of students
Note that we can use Stack<int> or Stack <float>, etc., as data types anywhere in the program just like you use normal data type, for example, to pass arguments, to receive return values, etc. Stack class shown below is like any other class except that parameter type T is used as data type:
1. template <class T>
2. class Stack
3. {public:Stack(); //default constructor
4. Stack(const Stack&); //Copy constructor
5. ~Stack(){ delete [] stack_array;} //destructor
6. Stack& operator=(const Stack&);//Assignment operator
7. int Size() const;
8. int empty() const; //returns 1 if stack is empty
9. T& top(); //returns top of stack
10. void pop(); //pops top of stack
11. void push(const T&); //pushes
12. template<class T>
13. friend ostream & operator<<(ostream & out1,Stack<T>&S);
14. private:
15. T *stack_array; // Stack of data integers,double,students
16. int tos;
17. int stack_size; // Stack size
18. };
Normally, if you declare and define any function, for example, say the constructor Stack within the class itself, like the constructor shown below, then there will be no need to use parameter type T:
Stack<T> :: Stack() { stack_array = new T[max]; stack_size = max; tos = -1;}
But if you define outside the class, you have to use qualifiers as shown below:
template <class T>
Stack<T> :: Stack(){ stack_array = new T[max]; stack_size = max; tos = -1;}
We define assignment operator as shown below:
template <class T>
Stack<T>& Stack<T> :: operator=(const Stack& S)
{ stack_array = new T[S.stack_size];
tos = S.tos;
stack_size = S.stack_size;
for(int i =0 ; i<size; i++)
stack_array[i] = S.stack_array[i];}
template <class T> // Size( ) function returns the size of the
stack. int Stack<T> :: Size() const { return tos+1;}
Prior to retrieving the data from the top of the stack, we need to ensure that stack is not empty. This is ensured by function empty() shown below:
template <class T>
int Stack<T> :: empty() const
{if(tos == -1) return 1;
else return 0;}
Push operation in Stack data structure is like adding an element on to the top of the stack. There is a need to increment top of stack ( tos) after each push operation.
template <class T>
void Stack<T> :: push(const T& val)
{ if( tos<stack_size-1 )
{ tos++;stack_array[tos] = val; }
}
In pop operation, we would eject the value from the top of the stack. This we would achieve by decrementing the top of stack (tos)
template <class T>
void Stack<T> :: pop()
{if(tos >= 0)tos--; }
In top() operation, we would use the value returned by the function for displaying the top of the stack. We would also decrement the tos, after top() operation:
template <class T>
T& Stack<T> :: top()
{ return (stack_array[tos--]); }
Also observe that we have declared << operator as friend of Stack class. As we want << operator to be friend of all instances of Stack class, we have declared as a template function as shown below:
template<class T>
friend ostream & operator<<(ostream & out1,Stack<T>&S)
{out1<<”
”<<”content”<<endl;
for ( int j=0 ; j<max; j++)
out1<<S.top()<<" : ";
}
Student class is a normal class that is provided to create an instance of students to template class. We would store the roll numbers on to stack, to be extracted on last-in-first-out basis. We have included operator << to be a friend of Student class
friend ostream & operator<<(ostream &src, Student &S)
{src<<S.Display(); // to display the roll no of the student
return src;}
In the next example, we would declare a student class . We would use this class to push instances of students on to Stack. We would also create instances of float Stack and int Stack to demonstrate the utility and power of the template.
Example 14.2: stacktemplate1b.cpp Implementation of Stack Data Structure Using Templates
#include<iostream>
#include<iomanip>
using namespace std;
const int max=10; // declares maximum of array size
class Student
{public:
Student(int roll); // constructor with roll no input
Student():rollNo(0){} //default constructor
~Student() {}; // default destructor
int Display() const {return rollNo;}
friend ostream & operator<<(ostream &src, Student &S)
{src<<S.Display();return src; }
private: int rollNo;
};
Student::Student(int roll):rollNo(roll){}
template <class T>
class Stack
{ public: Stack(); //default constructor
Stack(const Stack&); //Copy constructor
~Stack(){ delete [] stack_array;} //destructor
Stack& operator=(const Stack&);//Assignment operator
int Size() const;
int empty() const; //returns 1 if stack is empty
T& top(); //returns top of stack
void pop(); //pops top of stack
void push(const T&); //pushes
template<class T>
friend ostream & operator<<(ostream & out1,Stack<T>&S);
private:
T *stack_array; // Stack of data integers,double,students
int tos; //top of stack
int stack_size; // Stack size
};
template<class T>
ostream & operator<<(ostream & out1,Stack<T>&S)
{out1<<”
”<<”content”<<endl;
for ( int j=0 ; j<max; j++)
out1<<S.top()<<" : "; }
template <class T> //default constructor
Stack<T> :: Stack()
{stack_array = new T[max]; stack_size = max; tos = -1;}
//copy constructor
template <class T> //copy constructor
Stack<T> :: Stack(const Stack& S): stack_array(new T[S.size]),
tos(S.tos),stack_size(S.stack_size)
{for(int i =0 ; i<stack_size; i++) stack_array[i] = S.stack_array[i]; }
template <class T>
Stack<T>& Stack<T> :: operator=(const Stack& S)
{ stack_array = new T[S.stack_size];
tos = S.tos;
stack_size =S.stack_size;
for(int i =0 ; i<size; i++)
stack_array[i] = S.stack_array[i];
}
template <class T>
int Stack<T> :: Size() const { return tos+1;}
template <class T>
int Stack<T> :: empty() const
{if(tos == -1) return 1;
else return 0; }
template <class T>
void Stack<T> :: push(const T& val)
{if( tos<stack_size-1 )
{ tos++;stack_array[tos] = val; }
}
template <class T>
void Stack<T> :: pop()
{if(tos >= 0) tos--; }
template <class T>
T& Stack<T> :: top()
{return (stack_array[tos--]); }
void main()
{Stack<int> I; //Stack of integers
Stack<float> F; //Stack of floats
Stack<Student> stdStack;
for ( int i=0;i<max;i++)
{ I.push(i+10); F.push(i+20); stdStack.push(i+10000); }
cout<<"
The contents of the int stack"<<endl;
cout<<" "<<I;cout<<endl;
cout<<"
The contents of the float stack"<<endl;
cout<<" "<<F; cout<<endl;
cout<<"
The RollNos of the Student from stack"<<endl;
cout<<" "<<stdStack; cout<<endl;
cout<<"
endof program"<<endl;
}
/*Output :The contents of the int stack
Content 19 : 18 : 17 : 16 : 15 : 14 : 13 : 12 : 11 : 10 :
The contents of the float stack
Content 29 : 28 : 27 : 26 : 25 : 24 : 23 : 22 : 21 : 20 :
The RollNos of the Student from stack
content10009 : 10008 : 10007 : 10006 : 10005 : 10004 : 10003 : 10002 : 10001 : 10000*/
Normal function accepting normal instance of data, for example, a function called FindMax accepting array of integers.
You must pass an integer instance of the array: int FindMax(Array<int> &);
For a function that accepts Student array: void FindMax (Array<Student>&);
A generic template function declaration can handle all kinds of arrays: template <class T> void FindMax( Array<T>& );
A generic template function can also handle parameterized as well particular instances of a template: template <class T> void FindMax(Array<T>& , Array<float>);
A template class can have friends. These friends can be
We would refer the reader to Chapter 8 for general functions update. We have also seen in the previous example template friend function as friend operator << to stack template class.
We can declare a class or function as friend to template class. In the example that follows, we would include a friend function called FindSum() that will add elements of integer array. This program will use a non-template friend function FindSum() that will work only on integer arrays because it is a non-template friend function. We would also create instances of float stack and int stack.
Example 14.3: stacktemplate2b.cpp A Non-template Friend Function FindSum() That Will Work Only on Integer Arrays
#include<iostream>
using namespace std;
const int max=10; // declares maximum of array size
template <class T>
class Stack
{ public: Stack(); //default constructor
Stack(const Stack&); //Copy constructor
~Stack(){ delete [] stack_array;} //destructor
Stack& operator=(const Stack&);//Assignment operator
int Size() const;
int empty() const; //returns 1 if stack is empty
T& top(); //returns top of stack
void pop(); //pops top of stack
void push(const T&); //pushes
template<class T>
friend ostream & operator<<(ostream & out1,Stack<T>&S);
int FindSum( Stack<int> I ) // I is array of integers
private: T *stack_array; // Stack of data integers, double, students
int tos;
int stack_size; // Stack size
};
template<class T>
ostream & operator<<(ostream & out1,Stack<T>&S)
{out1<<”
”<<”content”<<endl;
for ( int j=0 ; j<max; j++)
out1<<S.top()<<" : ";}
//definition of friend FindSum().Gets access to private data
int FindSum( Stack<int> I ) // I is array of integers
{ int sum=0;
for ( int j=0 ; j<max; j++)
sum+=I.top();
return sum;
}
template <class T> //default constructor
Stack<T> :: Stack()
{stack_array = new T[max]; _size = max; = -1; }
template <class T> //copy constructor
Stack<T> :: Stack(const Stack& S): stack_array(new T[S.stack_size]),
tos(S.tos),stack_size(S.stack_size)
{ int i;
for(i =0 ; i<stack_size; i++)
stack_array[i] = S.stack_array[i];
}
template <class T>
Stack<T>& Stack<T> :: operator=(const Stack& S)
{ stack_array = new T[S.stack_size];
tos = S.tos;
stack_size =S.stack_size;
for(int i =0 ; i<size; i++)
stack_array[i] = S.stack_array[i];
}
template <class T>
int Stack<T> :: Size() const { return tos+1;}
template <class T>
int Stack<T> :: empty() const
{if(tos == -1) return 1;
else return 0;
}
template <class T>
void Stack<T> :: push(const T& val)
{if( tos<stack_size-1 )
{ tos++;stack_array[tos] = val; }
}
template <class T>
void Stack<T> :: pop()
{if(tos >= 0) tos--; }
template <class T>
T& Stack<T> :: top()
{ return (stack_array[tos--]); }
void main()
{ Stack<int> I; //Stack of integers
//populate int stack
for ( int i=0;i<max;i++)
{I.push(i+10);}
cout<<"
Use friend function int FindSum(Stack<int>)"
<<"
to calculate the sum of int Stack"<<endl;
int sum = FindSum(I);
cout<<"
Sum of integer Stack: " << sum<<endl;
cout<<"
endof program"<<endl;
}
/* Output Use friend function int FindSum(Stack<int>)
to calculate the sum of int Stack : Sum of integer Stack: 145 */
In Example 14.2, we have used extraction operator << as a template friend function of class Stack. In this section, we will introduce another very widely used data structure, i.e. array. Template declaration for Array class is given below:
Example 14.4: Template Declaration for Array Class is Given Below
template <class T>
class Array
{ public:
Array(int array_size=max); // constructor
Array(const Array&); //Copy constructor
~Array(){ delete [] array;} //destructor
Array& operator=(const Array&);//Assignment operator
T& operator[] (int i) {return array[i];}
const T& operator[](int i) const {return array[i];}
int Size() const { return array_size;}
template<class T>
friend ostream & operator<<(ostream & out1,Array<T>&S);
private:
T *array; // array of data integers,double,students
int array_size; // array size
};
Assignment operator =. First we would check if what we have on the left-hand side (lhs) and what we are equating with at the right-hand side (rhs) are one and the same. If same, there is no need to carry out the assignment operation. Hence, we return *this to called function Why return *this? You must appreciate that = operation allows chaining, i.e. we can write statement such as A=B=C=D=25. Then compiler first assigns D=25 and chains to C and thence to B & A. Hence, we need to return reference so that chaining is possible. Then before copying from the rhs, it is a good idea to delete what is on the lhs. Therefore, we use delete *array:
template <class T>
Array<T>& Array<T> :: operator=(const Array& S)
{if( this==&S)
return *this; // source & destination are same no need for = operation
delete *array; // delete destination prior to copy from rhs
array_size=S.Size();
array=new T[array_size];
for int i=0;i<array_size;i++)
array[i]=S[i];
return *this; // this is for chaining = operator allows chaining
}
int Size() const { return array_size;} is public accessory function provided to access private data array_size.
We have also declared << as a friend function of Array class
template<class T>
friend ostream & operator<<(ostream & out1,Array<T>&S)
{out1<<”
”<<”Index” <<” ”<<”content”<<endl;
for ( int j=0 ; j<S.array_size; j++)
out1<<”
”<<j<<” ”<<S[j];
}
Also note that if S[j] pertains to Student class, then it will invoke friend operator << defined in Student class.
int Display() const {return rollNo;}
friend ostream & operator<<(ostream &src, Student &S)
{src<<S.Display();return src; }
We have included overloading of operator [ ] in Array class as shown below:
T& operator[] (int i) {return array[i];}
const T& operator[](int i) const {return array[i];}
Please note that array has been declared as pointer belonging to data type T. Given off set or cell number of the array, operator [ ] returns a reference of type T or const T. Because of these overloading operators, we could use statements like
for ( int i=0;i<I.Size();i++)
{ I[i]=i+10;
F[i]=i+20.0;
pstd=new Student(i+10000);
stdarray[i]=*pstd;
}
Finally, observe that overloaded friend operator << has allowed us to use statements like cout<<I; in the main program. Student class is a normal class that is provided to create an instance of students to template class. Ex 2 at the end of the chapter gives a complete solution.
In the next program, we will use a template friend function FindSum() that will work on all types of arrays because its a template friend function. We will also declare operator << (extraction operator) as friend of Stack class.
Note that we have placed both these functions above public and private declarations in Stack class. Friend in any case gets access to private data. Hence, it can be above public and private declarations of the class. This is one of the ways to declare and define friend functions.
Note further that we have declared friend functions to be type-specific. This means that integer Stack will be a friend of Stack<int> class only. Similarly, float Stack will a be friend of Stack<float class. Hence, we have omitted template <class T> in our friend function definitions.
In the example that follows, we will also show you how to pass the template object as an argument to a function FindSum.
Example 14.5: stacktemplate3b.cpp Type-specific Friend Functions
#include<iostream>
using namespace std;
const int max=10; // declares maximum of array size
template <class T>
class Stack
{friend void FindSum( Stack<T> I ) // I is stack of integers
{ T sum=T(0);
for ( int j=0 ; j<max; j++)
sum+=I.top();
cout<< sum<<endl;
}
friend ostream & operator<<(ostream & out1,Stack<T>&S)
{out1<<”
”<<”content”<<endl;
for ( int j=0 ; j<S.Size(); j++)
out1<<S.top()<<" : ";
return out1;
}
public: Stack(); //default constructor
Stack(const Stack&); //Copy constructor
~Stack(){ delete [] stack_array;} //destructor
Stack& operator=(const Stack&);//Assignment operator
oint Size() const;
int empty() const; //returns 1 if stack is empty
T& top(); //returns top of stack
void pop(); //pops top of stack
void push(const T&); //pushes
void SetTos(){ tos=max-1;}
private:
T *stack_array; // Stack of data integers,double,students
int tos;
int stack_size; // Stack size
};
template <class T> //default constructor
Stack<T> :: Stack()
{stack_array = new T[max]; stack_size = max; tos = -1;}
template <class T> //copy constructor
Stack<T> :: Stack(const Stack& S): stack_array(new T[S.stack_size]),
tos(S.tos),stack_size(S.stack_size)
{ int i;
for(i =0 ; i<stack_size; i++)
stack_array[i] = S.stack_array[i];
}
template <class T>
Stack<T>& Stack<T> :: operator=(const Stack& S)
{ stack_array = new T[S.stack_size];
tos = S.tos;
stack_size =S.stack_size;
for(int i =0 ; i<size; i++)
stack_array[i] = S.stack_array[i];
}
template <class T>
int Stack<T> :: Size() const
{return tos+1;}
template <class T>
int Stack<T> :: empty() const
{if(tos == -1) return 1;
else return 0;
}
template <class T>
void Stack<T> :: push(const T& val)
{if( tos<stack_size-1 )
{ tos++;stack_array[tos] = val; }
}
template <class T>
void Stack<T> :: pop()
{if(tos >= 0) tos--; }
template <class T>
T& Stack<T> :: top()
{ return (stack_array[tos--]); }
void main()
{Stack<int> I1; //stack of integers
Stack<float> F1; //stack of floats
// fill the data in to all three stacks
for ( int i=0;i<max;i++)
{ I1.push(i+10);
F1.push(i+20.0);
}
cout<<"
output using friend << operator"<<endl;
cout<<"
The contents of the stack of int type"<<endl; cout<<I1;
cout <<"
The contents of the stack of float type"<<endl; cout<<F1;
//tos() function decrements tos for each display till tos=-1
//To Go to top of stack Call SetTos() function for reusing Stack
F1.SetTos(); I1.SetTos();
cout<<"
Use friend function T FindSum(Stack<T>)"
<<"
to calculate the sum of T type stack"<<endl;
cout<<"
Sum of integer stack : ";FindSum(I1);
cout<<"
Sum of float stack : "; FindSum(F1);
}
/*Output: out put using friend << operator
The contents of the stack of int type
Content 19 : 18 : 17 : 16 : 15 :
The contents of the stack of float type
Content 29 : 28 : 27 : 26 : 25 :
Use friend function T FindSum(Stack<T>)
to calculate the sum of T type stack
Sum of integer stack : 145 Sum of float stack : 245 */
While handling static member data and member functions, all the rule that apply to static declarations with respect to ordinary classes also apply for template classes and member functions. Static declaration in template allows each instant of template to have its own static data. For example, if we declare a static member data to stack like numberOfStacks in our array class, then each instantiation of Student array and integer array will have its own numberOfStacks to keep track of how many student arrays or integer arrays have been created.
Example 14.6: stacktemplate5b.cpp Program to Demonstrate Static Member
//functions and static data
#include<iostream>
using namespace std;
const int max=10; // declares maximum of stack size
class Student
{ public: Student(int roll); // constructor with roll no input
Student():rollNo(0){} //default constructor
~Student() {}; // default destructor
private: int rollNo;
};
Student::Student(int roll):rollNo(roll){}
template <class T>
class Stack
{friend void FindSum( Stack<T> I ) // I is stack of integers
{ T sum=T(0);
for ( int j=0 ; j<max; j++) sum+=I.top();
cout<< sum<<endl;
}
friend ostream & operator<<(ostream & out1,Stack<T>&S)
{out1<<”
”<<”content”<<endl;
for ( int j=0 ; j<S.Size(); j++)
out1<<S.top()<<" : ";
return out1;
}
public: Stack(); //default constructor
Stack(const Stack&); //Copy constructor
~Stack(){ delete [] stack_array;} //destructor
Stack& operator=(const Stack&);//Assignment operator
int Size() const;
int empty() const; //returns 1 if stack is empty
T& top(); //returns top of stack
void pop(); //pops top of stack
void push(const T&); //pushes
void SetTos(){ tos=max-1;} // To go to top of stack
static int GetNumberOfStacks() { return numOfStacks;}
private:
T *stack_array; // Stack of data integers,double,students
int tos;
int stack_size; // Stack size
static int numOfStacks; // static data to keep track of number of stacks
};
// template instantiation of static member
template < class T>
int Stack<T>::numOfStacks=0;
template <class T> //default constructor
Stack<T> :: Stack()
{ stack_array = new T[max];
stack_size = max;
tos = -1;
numOfStacks++;
}
template <class T> //copy constructor
Stack<T> :: Stack(const Stack& S): stack_array(new T[S.stack_size]),
tos(S.tos),stack_size(S.stack_size)
{ int i;
for(i =0 ; i<stack_size; i++)
stack_array[i] = S.stack_array[i];
numOfStacks++;
}
template <class T>
Stack<T>& Stack<T> :: operator=(const Stack& S)
{ stack_array = new T[S.stack_size];
tos = S.tos;
stack_size =S.stack_size;
for(int i =0 ; i<size; i++)
stack_array[i] = S.stack_array[i];
}
template <class T>
int Stack<T> :: Size() const { return tos+1;}
template <class T>
int Stack<T> :: empty() const
{if(tos == -1) return 1;
else return 0;
}
template <class T>
void Stack<T> :: push(const T& val)
{if( tos<stack_size-1 )
{ tos++;stack_array[tos] = val; }
}
template <class T>
void Stack<T> :: pop()
{if(tos >= 0) tos--; }
template <class T>
T& Stack<T> :: top()
{ return (stack_array[tos--]); }
void main()
{ Stack<int> I1; //stack of integers
Stack<float> F1; //stack of floats
Stack<Student> stdStack; // stack of Students
// fill the data in to all three stacks
for ( int i=0;i<max;i++)
{I1.push(i+10); F1.push(i+20.0); stdStack.push(i+10000);
}
// declare & fill the data in Second set of Stacks
Stack<int> I2; //Stack of integers
Stack<float> F2; //Stack of floats
Stack<Student> stdStack2; // Stack of students
// fill the data in to all three stacks for second set
for ( i=0;i<I2.Size();i++)
{ I2.push(i+10); F2.push(i+20.0); stdStack2.push(i+10000);
}
cout<<"
Display static data using full class specification.."<<endl;
cout<<"
integers Stacks"<<" "<<Stack<int>::GetNumberOf Stacks()<<endl;
cout<<" float Stacks"<<" "<<" "<<Stack<float>::GetNumberOf Stacks()<<endl;
cout<<" Student Stacks"<<" "<<Stack<Student>::GetNumberOf Stacks()<<endl;
cout<<"
Display static data using object say I2 , F2 , stdStack2.." <<endl;
cout<<"
integers Stacks"<<" "<<I2.GetNumberOfStacks()<<endl;
cout<<" float Stacks"<<" "<<" "<<F2.GetNumberOfStacks() <<endl;
cout<<" Student Stacks"<<" "<<stdStack2.GetNumberOfStacks() <<endl;
}
/*Output Display static data using full class specification.
integers Stacks 2
float Stacks 2
Student Stacks 2
Display static data using object say I2 , F2 , stdStack2..
integers Stacks 2
float Stacks 2
Student Stacks 2*/
For dealing with exceptions while using in conjunction with templates, the programmer has the following options:
Recall from Chapter 11 on exceptions tha t we have defined an exception class stackfullexception {} and stackemptyexception {} with an empty body with in the class definition so that we could use it as a tool to catch the exception and enter the catch block. The catch block, then, informs the user and makes necessary rectification or exits the program. Note that this exception class has no body. Its sole purpose is to give entry to catch block. As an example, while programming Stack operations, we can include two exceptions, namely, stackfullexception and stackemptyexception, within the template class Stack as shown below:
class Stack
{public: ………………….
// Exception classes
class stackfullerror {};
class stackemptyerror {}
};
When an exception object is thrown, control passes to catch block wherein corrective mechanisms are in place. Note that we have to use Stack<string> as we are using templates and string specifies the parameter type.
catch(Stack<string>::stackfullerror)
{ cout<<”
stack full exception . Cannot be pushed on to stack:”<<endl;
cout<<”
Exiting the catch block of stackfull exception ..”<<endl;
}
Ex 3 at the end of the chapter gives complete solution.
18.118.2.240