Beruflich Dokumente
Kultur Dokumente
The template enables us to define generic classes and generic functions, which in turn help create families of classes and
functions They avoid duplication of code and thus play a vital role in substantial improvement of the programming
efficiency. Programming with templates is often referred to as generic programming.
There are two categories of templates: a) Class template, which is used to create a family of classes with the same member
functions but with different types of data. b) Function template, which is used to create a family of functions performing
the same operation but over different types of data.
Function Template
Template is a method for writing a single function of class for a family of similar functions and classes in a generic
manner. When a single generic function is written with generic type arguments for a family of similar functions is called as
a Function Template.
The general form of a function template is as follows:
template < class T>
type function_name(arguments of type T)
{
//Usage of type T whenever required
}
Example
template<class T> void max (T a, T b)
{
if ( a > b )
float f = 19.25;
www.edutechlearners.com
Page 1
char c = x;
cout << a=;
display(a);
cout << f=;
display(f);
cout << c=;
display(c);
return 0;
}
Input Output:
a=5
f = 19.25
c=x
Explanation
In Program, the function template display() is defined with an argument of anonymous type T. The purpose of the function
is to display the values passed to it. In the main(), three calls are made to the function to display an integer, a float value
and a character. The statement display(a); displays the value of the variable a; display(f); displays the value of the variable
f and the statement display(c); displays the character stored in the variable.
Program: To illustrate Function Template
#include<iostream.h> template<class T>
void swap( T& first, T& second)
{
T temp;
temp = first;
first = second;
second = temp;
}
int main()
{
int ix, iy;
float fx, fy;
cout << Enter any two integers \n;
cin >> ix >> iy;
cout << Enter any two floating point values;
cin >> fx >> fy;
swap(ix, iy);
cout << After swapping integers \n;
cout << ix = << ix;
cout << iy = << iy;
swap(fx, fy);
cout << After swapping Float;
cout << fx = << fx;
cout << fy = << fy;
}
www.edutechlearners.com
Page 2
Input Output:
Enter any two integers 10 20
Enter any two floating point values 11.22 33.44
After Swapping integer ix = 20 iy = 10
After Swappping Float fx = 33.44 fy = 11.22
display(OOPS);
return 0;
}
Input Output:
In normal display() 10
In template display() 5.25 In template display() d
In template display OOPS
Explanation
In Program, the function call display(10); finds an exact match with the normal function display(), which also takes an
argument of int type and the normal function gets called. In all the other cases, the function template display() gets called
to display the values, since each of these fails to match with the normal function and an exact match could be created with
the function template. The last case of resolving the function calls base on the overloading resolution rules does not arise.
Class Template
www.edutechlearners.com
Page 3
If the class template is provided with constructor, we can initialize the objects while they are declared. The syntax of
declaration would then be:
tagname<type> object_name(arguments);
Let us now write a class template for the above two classes.
www.edutechlearners.com
Page 4
T x;
public:
scalar()
{
x = 0;
}
scalar(T y)
{
x = y;
}
T sum(scalar b)
{
T t;
t = x + b.x;
return t;
}
};
int main()
{
scalar<int> a(6), b(7);
scalar<float> r(5.6), s(7.5);
Page 5
www.edutechlearners.com
Page 6
Explanation
In Program, the class template temp is defined to take two types T1 and T2 as parameters. The member data a and b are
declared to be of type T1 and T2 respectively. The class template includes a constructor with an argument of type T1 and an
argument of T2 type, which are assigned to the member data of the class template. The member function display() is just to
display the members of an object of the class template.
t1, declared to be an object of the class template temp with int type as its parameter and float as its second type
parameter, is initialized with the values 5 and 6.25. t2, declared to be an object of the class template temp with char type
as its parameter and int as its second type parameter, is initialized with the values a and 8. t3, declares to be an object
of the class template temp with char type as its parameter and float as its second type parameter, is initialized with the
values b and 7.45. The values of all the three objects are then displayed.
Non-type Template Parameters
We know that a class template may have multiple parameters. Some of the parameters can be of ordinary non-type.
Examples of ordinary non-type include built-in types like int, float, etc. The values passed to non-type parameters must
be constants.
Consider the following example:
template<class T, int size> class vector
{
T a[size]; };
vector<int, 5> v1;
v1 is created as a vector of int type and size five.
vector<float, 4> v2;
v2 is created to be a vector of float type and of size 4.
Program: Non-type Template Parameter
#include<iostream.h>
template<class T, int size>
{
T a[size];
public:
void get()
{
for(int i = 0; i < size; i++)
cin >> a[i];
}
void display()
{
for(int i = 0 ; i < size; i++)
cout << a[i] << ;
}
};
www.edutechlearners.com
Page 7
int main()
{
vector<int , 5> v1;
vector<float, 5> v2;
www.edutechlearners.com
Page 8
void display()
{
cout << a = << a << \n; cout << b = << b <<\n;
}
};
int main()
{
In the main(), l is declared to be an object of beta<int> type. The statement l.get() on its execution, accepts the member
data values of the object l, which are of int type and the statement l.display(); on its execution, displays the member data
values. f is declared to be an object of beta<float> type. The statement f.get(); on its execution accepts the member data
values of the object f, which are of float type and the statement f.display(); on its execution, displays the member data
values.
Templates and Friends
We have seen that functions and entire classes can be declared as friend of nontemplate classes/
www.edutechlearners.com
Page 9
With class templates, friendship can be established between a class template and a global function, a member function
of another class or even an entire class.
We assume that we have defined a class template for a class named X with a single type parameter T, as in:
template <typename T> class X
Under this assumption, it is possible to make a function f1 a friend fo every class-template specialization instantiated
from the class template for class X. To do so, use a friendship declaration of the form.
friend void f1();
For example, function f1 is a friend of X<double>, X<string> and X<employee>, etc.
It is also possible to make a function f2 a friend of class-template specialization X<float> but not a friend of classtemplate specification X<string>.
You can declare that a member function of another class is a friend of any class-template specialization generated from
the class template. To do so, the friend declaration must qualify the name of the other classs member function using the
class name and the scope resolution operator, as in:
friend void A::f3();
The declaration makes member function f3 of class A a friend of every class-template specialization instantiated from
the preceding class template. For example, function f3 of class A is a friend of X<double>, X<string> and
X<employee>, etc.
As with a global function, another classs member function can be a friend of only a classtemplate specialization with the same type argument. A friendship declaration of the form
friend void C<T>::f4(X<T> &);
for a particular type T such as float makes member function
C<float>::f4(X <float> &)
a friend function of only class-template specialization X<float>.
In some cases, it is desirable to make an entire classs set of member functions friends of a class template. In this case, a
friend declaration of the form
friend class Y;
makes every member function of class Y a friend of every class-template specialization produced from the class
template X.
Finally, it is possible to make all member functions of one class-template specialization friends of another classtemplate specialization with the same type argument. For example, a friend declaration of the form:
www.edutechlearners.com
Page 10
Division by zero, Array subscript out of bounds. Examples of runtime errors due to internal factors include
Runtime out of memory, Printer out of paper, etc. The term exception is used to represent a runtime error and
exception handling is about anticipating exceptions, identifying them and taking corrective steps when they occur
thereby avoiding abnormal termination of a program.
Exception Handling Mechanism
A structured approach toward exception handling has been made a part of C++. At the outset, exception-handling code
consists of two segments. The first segment is responsible for detecting the errors and information them to the errorhandling routing and the second one, the error handling routine, is for receiving the errors and initiate appropriate
measures. Central to exception handling in C++ are three keywords: try, throw, and catch.
A block of statements enclosed within braces, which may raise exceptions, follows the keyword try. The block is called
the try block.
try
{ .
. throw exception;
}
within the try block, if an exception is generated it is informed to the error handler routine with the help of throw
keyword. If an exception is informed to the error handler routing by the throw statement, the exception is said to have
been thrown to the error handler routine.
www.edutechlearners.com
Page 11
catch(type argument)
{
. // Statements that handle
. //the exception thrown by the
. // try block
}
The catch block is responsible for receiving (catching) the exception thrown by the throw statement of the try block
and handling it appropriately.
A catch block that catches an exception must follow the try block that throws the exception.
Relationship between try block and catch block is shown in figure.
An exception is basically an object, which is used to transmit the error situation to the catch block so that it can take
corrective steps. The object can be built-in type value like int, char, float, etc. or it can also be a user-defined type
value like an object of a class.
Execution sequence of a program, which contains a try and a matching catch block, is as follows:
If the try block does not detect an exception then the matching catch block is simply skipped during execution.
If try block detects and throws an exception, the control is transferred from the try block and reaches the catch statement of
the matching catch block (i.e., the catch block the argument type of which matches with that of the exception thrown by the
try block). The catch block receives the exception and handles it. After the execution of the catch block, the control reaches
the first statement after the closing brace of the catch block. Note that the control is not transferred back to the try block
that threw the exception.
If the try block detects an exception and throws it and there is no matching catch block then the program is terminated.
If the try block does not detect any exception then the matching catch block is simply skipped during execution.
Program: Division by Zero Exception
#include<iostream.h>
int main()
{
int a, b;
try
{
if ( b!=0)
cout<<a/b = << a/b;
www.edutechlearners.com
Page 12
else
throw b;
}
catch(int x)
{
cout<< Exception caught = << x;
}
return 0;
}
Input Output:
First Run
Enter values of a and b 4 2
a/b = 2
Second Run
Enter values of a and b 4 0
Exception caught = 0
Explanation
In Program, a and b are declared to be variables of int type. The values of both are accepted with the statement cin>> a
>> b;. The purpose of the program is to display the value of the expression a/b. Here we foresee the possibility of b, the
denominator, taking a value zero, which gives rise to an exception.
In the first run we accept 4 and 2 to the variables a and b respectively. In the try block the value of 4/2 is displayed and
no exception is detected. As a result, the catch block is skipped.
In the second run we accept the values 4 and 0 to a and b respectively. Since b is zero, the exception division by zero
is detected by the try block and throws b. The catch block receives the exception and displays the message exception
caught = 0. After the execution of the catch block, the control reaches the return 0 statement of the main(), which when
executed causes the exit of the main().
Program: Array out of Bounds Exception
#include<iostream.h>
int main()
{
Page 13
catch(int j)
{
cout<<Array out of bounds = << j;
}
return 0;
}
Input Output: 1 3 5 7 9
Array out of bounds = 5
Explanation
In Program, the array a is int type and of size 5 is initialized with five values. We set up a loop in the try block to display the
elements in the array and intentionally we try to display the elements beyond the array. The attempt to go beyond the array
gives rise to an exception, which is thrown by the try block and the catch block catches it and displays the message Array out
of bounds = 5.
The control then reaches the end of the main().
Page 14
Explanation
In program, the function divide() is defined with two arguments a and b of int type. The purpose of the function is to
display the value of a/b. The function displays the value of a/b if b is non-zero and throws an exception if b is zero
(Division by zero).
In the main(), the function divide() is invoked twice. The call divide(4,2); display the value of 4/2, which is 2. But the
second function call divide(4,0); throws an exception since the division by zero is not defined. The catch block which
follows the function call receives the exception and displays the message exception caught = 0.
Here the function divide() throws an exception and the exception is handled by main().
Single Try Block and Multiple Catch Blocks
There may be situations wherein a program segment gives rise to more than one exception subject to different conditions,
which are mutually exclusive. At any point of time only one condition will be true and the segment throws the corresponding
exception. In this situation, the program segment is embedded with a single try block and multiple catch blocks, one for each
exception, will follow the try block. The catch block, the argument of which matches with that of the exception thrown, will
get executed.
After the catch block is executed, the control is transferred to the first statement after all the catch blocks. If the
arguments of more than one catch block match with the type of the exception then the first catch block that matches will
get executed. If there is no matching catch block then the program is abnormally terminated.
Program: Single Try Block and Multiple Catch Block
#include<iostream.h>
int main()
{
int x;
}
catch( int i)
{
cout << Exception caught << I;
www.edutechlearners.com
Page 15
}
catch(float f)
{
cout <<Exception Caught = << f;
}
catch(char c)
{
cout<< Exception caught << c;
}
catch(char* cp)
{
cout <<Exception caught = << cp;
}
return 0;
}
Input Output:
First-Run
www.edutechlearners.com
Page 16
}
catch(. . . )
{
cout << Exception caught ;
}
return 0;
}
Input Output:
Enter a value for x 3
exception caught
Explanation
Same as previous program, the try block can throw four types of exceptions and the single catch block catches each of
them.
Re-throwing an Exception
If need be, a catch block can rethrow an exception that is caught by it. It is done with the use of the statement throw;
without specifying any exception after the keyword throw.
Program: Re-throwing an Exception
#include<iostream.h>
void divide(int a, int b)
{
try
{
if( b ! = 0 )
www.edutechlearners.com
Page 17
www.edutechlearners.com
Page 18
Program: Specifications
#include<iostream.h>
void test(int x) throw(int, float, char)
{
switch(x)
{
case 1: throw x;
break;
case 2: throw x;
break;
case 3: throw (double) x;
break;
Page 19
function call test(2); throws char type exceptions and it is received by the catch block with char type as the argument.
The third call to the function test(3); tries to throw an exception of type double, but the function can not throw double
type exception, and, this results in abnormal program termination. The function call test(4) throws float type exception
and it is caught by the catch block meant for it.
If we intend to prevent a function from throwing any type of exceptions, we can do so by not specifying anything in the
throw list. The general form of the function appears as follows:
type function(args-list) throw()
{
statements
}
Here function is prevented from throwing any exception. In case it throws an exception, it results in abnormal
termination of the program.
Exception Handling and Inheritance
We can anticipate exceptions to arise while we make one class inherit from another class.
Program: Exception Handling and Inheritance
#include<iostream.h>
class author
{
Page 20
int main()
{
book b;
try
{
b.get();
b.display();
}
catch(book b)
{
cout<< Caught book exceptions ;
return 0;
}
Input Output: Enter author name Vishal
Enter Title OOPS Notes
Page 21
Stack Unwinding
When an exception is thrown but not caught in a particular scope, the function call stack is
unwound, and an attempt is made to catch the exception in the next outer trycatch block. Unwinding the function
call stack means that the function in which the exception was not caught terminates, all local variables in that function
are destroyed and control returns to the statement that originally invoked that function. If a try block encloses that
statement, an attempt is made to catch the exception. If a try block does not enclose that statement, stack winding occurs
again. If no catch handler ever catches this exception, function terminate is called to terminate the program.
Program: Stack Unwinding
#include<iostream.h>
void function3( )
{
cout<<"In Function 3"<<endl;
throw 0;
}
void function2( )
{
cout<<"Function 3 is called inside function2"<<endl;
function3( );
}
void function1( )
{
cout<<"function 2 is called inside function 1" <<endl;
function2( );
}
int main()
{
try
{
cout<<"function 1 is called inside main"<<endl;
function1( );
}
catch(int x)
{
cout<<"Exception occurred" << x <<endl;
cout<<"Exception handled in main"<<endl;
}
return 0;
}
Input Output
Function1 is called inside main
Function2 is called inside function1
Function3 is called inside function2
In function3
Exception occurred 0
Exception handled in main
www.edutechlearners.com
Page 22
Explanation
In main, the try block calls function1. Next, function1 calls function2, which in turn calls function3. function3 throws
0(zero) . However, because no try block encloses the throw statement, stack unwinding occurs function3 terminates then
control returns to the statement in function2 that invoked function3 Because no try block encloses, stack unwinding occurs
again function2 terminates and control returns to the statement in function1 that invoked function2. Because no try encloses,
stack unwinding occurs one more time function1 terminates and control return to the statement in main that invoked
function1. The try block encloses this statement, so the first matching catch handler located after this try block catches and
process the exception.
Constructor,
What happens when an error is detected in a constructor? For example, how should an objects constructor respond when new
fails because it was unable to allocate required memory for storing that objects internal representation?
Because the constructor can not return a value to indicate an error, we must choose an alternative means of indicating that the
object has not been constructed properly. Once scheme is to return the improperly constructed object and hope that anyone
using it would make appropriate tests to determine that it is in an inconsistent state. Another scheme is to set some variable
outside the constructor. The preferred alternative is to require the constructor to throw an exception that contains the error
information, thus offering an opportunity for the program to handle the failure.
Before an exception is thrown by a constructor, destructors are called for any member objects built as part of the object
being constructed. Destructors are called for every automatic object constructed in a try block before an exception is
thrown. Stack unwinding is guaranteed to have been completed at the point that an exception handler begins executing. If
a destructor invoked as a result of stack unwinding throws an exception, terminate is called.
If an object has member objects and if an exception is thrown before the outer object is fully constructed, then destructors
will be executed for the member objects that have been constructed prior to the occurrence of the exception. If an array
of objects has been partially constructed when an exception occurs, only the destructors for the constructed objects in the
array will be called.
An exception could preclude the operation of code that would normally release a resource, thus causing a resource leak.
One technique to resolve this problem is to initialize a local object to acquire the resource. When an exception occurs, the
destructor for that object will be invoked and can free the resources.
www.edutechlearners.com
Page 23
www.etd.co.in
Page 24