Download as pdf or txt
Download as pdf or txt
You are on page 1of 17

Unit IV

Templates

Templates are the foundation of generic programming, which involves writing code in a
way that is independent of any particular type. A template is a blueprint or formula for
creating a generic class or a function.

Two kinds of templates


1) Function Template
2) Class Template

Template Allow single template with generic data types

1) Function Template (Generic Functions)

Syntax:
template <class T,…>
returntype funname(arg)
{
//body of template fun
}

Example:
#include<iostream>
using namespace std;
template<class T>
class swapping
{
public:
void swap(T &x,T &y)
{
T tt;
tt=x;
x=y;
y=tt;
}
};

int main()
{
int a=10,b=20;
float j=30,k=40;
cout<<"before swap"<<a<<b;
swap(a,b);
cout<<"after swap"<<a<<b;
cout<<"before swap"<<j<<k;
swap(j,k);
cout<<"after swap"<<j<<k;
return 0;
}

https://www.youtube.com/watch?v=8XTMa3GhZwg

Class Template (Generic Classes)

Syntax

template <class T,…>


class classname
{
//Attributes
//Methods
};

Example
#include<iostream>
using namespace std;
template <class T> //prefix code
class addition //template class
{
public:
T add (T,T);
};
template <class T>
T addition <T>:: add(T n1,T n2)
{
T result;
result=n1+n2;
return result;
}
int main()
{
addition <int>obj1;//object of class
addition<long>obj2;
int a=10,b=20,c;
long l=11,j=30,k;
c=obj1.add(a,b);
cout<<"int val"<<c;
k=obj2.add(l,j);
cout<<"long val"<<k;
return 0;
}

The Power of Templates


Templates help to achieve one of the most elusive goals in programming: the creation of
reusable code. Through the use of template classes you can create frameworks that can be
applied over and over again to a variety of programming situations.

For example, consider the stack class. When it could only be used to store integer values. Even
though the underlying algorithms could be used to store any type of data, thehard-codingof the
data type into the stack class severely limited its application. However, by making stack into
a generic class, it can create a stack for any type of data.

Generic functions and classes provide a powerful tool that you can use to amplify your
programming efforts. Once you have written and debugged a template class, you have a solid
software component that you can use with confidence in a variety of different situations. You
are saved from the tedium of creating separate implementations for each data type with which
you want the class to work.

Template functions and classes are already becoming commonplace in programming. For
example, the STL (Standard Template Library) defined by C++ is, as its name implies, built
upon templates. although templates add a layer of abstraction, they still ultimately compile
down to the same, high-performance object code

Class Template with Multiple parameters

#include<iostream>
using namespace std;

// Class template with two parameters


template<class T1, class T2>
class Test
{
T1 a;
T2 b;
public:
Test(T1 x, T2 y)
{
a = x;
b = y;
}
void show()
{
cout << a << " and " << b << endl;
}
};

// Main Function
int main()
{
// instantiation with float and int type
Test <float, int> test1 (1.23, 123);

// instantiation with float and char type


Test <int, char> test2 (100, 'W');

test1.show();
test2.show();

return 0;
}
Output:
1.23 and 123
100 and W

Function Template with Multiple parameters

#include <iostream>
using namespace std;
template<class X,class Y>
void fun(X a,Y b)
{
std::cout << "Value of a is : " <<a<< std::endl;
std::cout << "Value of b is : " <<b<< std::endl;
}
int main()
{
fun(15,12.3); return 0;
}
/* Output : Value of a is : 15 Value of b is : 12.3 */

Error can be of 2 types


1) Compile time
2) Run time also knows as exception

Example:
x/0;

Exception handling

It is conversion of system error message into user friendly error message. Exception is an
event which occurs during execution of the program which disrupts normal flow of a
program.

Exception handling mechanism


1) find problem
2) throw exception
3) catch exception
4) handle exception

Exceptions provide a way to transfer control from one part of a program to another.
C++ exception handling is built upon three keywords: try, catch,and throw.

 throw − A program throws an exception when a problem shows up. This is done using
a throw keyword.
 catch − A program catches an exception with an exception handler at the place in a
program where you want to handle the problem. The catch keyword indicates the
catching of an exception.
 try − A try block identifies a block of code for which particular exceptions will be
activated. It's followed by one or more catch blocks.
Assuming a block will raise an exception, a method catches an exception using a combination
of the try and catch keywords. A try/catch block is placed around the code that might generate
an exception. Code within a try/catch block is referred to as protected code, and the syntax for
using try/catch as follows

try {
// protected code
} catch( ExceptionName e1 ) {
// catch block
} catch( ExceptionName e2 ) {
// catch block
} catch( ExceptionName eN ) {
// catch block
}

Block throwing Exception


Function invoke by try block throwing exception

Multiple Catch Statement


In multiple catch statements type is matched

Std Exceptions
Sr.No Exception & Description

1 std::exception
An exception and parent class of all the standard C++ exceptions.

2 std::bad_alloc
This can be thrown by new.

3 std::bad_cast
This can be thrown by dynamic_cast.

4 std::bad_exception
This is useful device to handle unexpected exceptions in a C++
program.

5 std::bad_typeid
This can be thrown by typeid.

6 std::logic_error
An exception that theoretically can be detected by reading the code.

7 std::domain_error
This is an exception thrown when a mathematically invalid domain
is used.

8 std::invalid_argument
This is thrown due to invalid arguments.

9 std::length_error
This is thrown when a too big std::string is created.

10 std::out_of_range
This can be thrown by the 'at' method, for example a std::vector and
std::bitset<>::operator[]().

11 std::runtime_error
An exception that theoretically cannot be detected by reading the
code.

12 std::overflow_error
This is thrown if a mathematical overflow occurs.

13 std::range_error
This is occurred when you try to store a value which is out of range.

14 std::underflow_error
This is thrown if a mathematical underflow occurs.

Simple calculator program using Exception Handling


#include<iostream>
using namespace std;
class calculator
{
int x,y,result;
public:

calculator()
{
x=y=result=0;
}

void getdata()
{
cout<<"\nEnter Two Numbers\n";
cin>>x>>y;
}

void addition()
{
result=x+y;
if(result>32000)
throw 'a';
else
cout<<"Addition ="<<result;
}

void substraction()
{
result=x-y;
if(result<0)
throw 'b';
else
cout<<"Subtraction ="<<result;

void multiplication()
{
result=x*y;
if(result>32000)
throw 'c';
else
cout<<"Product ="<<result;
}

void division()
{
if(y==0)
throw 'd';
else
{
result=x/y;
cout<<"Division ="<<result;
}
}
};

int main()
{
calculator cal;
int ch;
cout<<"1. Add\t2.Subtract\t3.Multiply\t4.Divide\n";
cout<<"\n Enter your choice\n";
cin>>ch;
try
{
switch(ch)
{

case 1:
cal.getdata();
cal.addition();
break;

case 2:
cal.getdata();
cal.substraction();
break;

case 3:
cal.getdata();
cal.multiplication();
break;

case 4:
cal.getdata();
cal.division();
break;

default:
cout<<"Wrong input";
}
}
catch(char c)
{
if (c=='a')
cout<<"Sum is too long! ";
else if(c=='b')
cout<<"Subtraction is a negative value! ";
else if(c=='c')
cout<<"Product is too long.! ";
else
cout<<"Division by zero!";
}
return 0;
}

Re throw
Re-throwing an exception in C++ involves using the throw statement without an argument
inside a catch block. When you use throw; without providing an exception object, it rethrows
the currently caught exception, allowing it to propagate up the call stack. This is useful when
you want to catch an exception, perform some handling or logging, and then let the exception
continue its journey up the call stack.
Rethrowing an exception in C++ involves catching an exception within a try block and
instead of dealing with it locally throwing it again to be caught by an outer catch block. By
doing this. we preserve the type and details of the exception ensuring that it can be handled
at the appropriate level within our program.
This approach becomes particularly valuable when managing exceptions at multiple levels
or when additional actions need to be performed before resolving the exception.

#include <iostream>
#include <stdexcept>
using namespace std;

// Function to perform division


int divide(int numerator, int denominator)
{
try {
if (denominator == 0) {
// Throw a runtime_error if attempting to divide
// by zero
throw runtime_error("Division by zero!");
}
// Perform the division and return the result
return numerator / denominator;
}
catch (const exception& e) {
cout << "Caught exception in divide(): " << e.what()
<< endl;
// Rethrow the caught exception to handle it at a
// higher level
throw;
}
}

// Function to calculate the sum of two numbers


int calculateSum(int a, int b)
{
try {
if (a < 0 || b < 0) {
// Throw an invalid_argument exception for
// negative numbers
throw invalid_argument(
"Negative numbers not allowed!");
}
// Calculate and return the sum
return a + b;
}
catch (const exception& e) {
cout << "Caught exception in calculateSum(): "
<< e.what() << endl;
// Rethrow the caught exception to handle it at a
// higher level
throw;
}
}

int main()
{
try {
// Calculate the sum of 10 and the result of
// dividing 20 by 2
int result = calculateSum(10, divide(20, 2));
cout << "Result: " << result << endl;

// Attempt to divide by zero, triggering an


// exception
int invalidResult = calculateSum(5, divide(10, 0));
cout << "Invalid Result: " << invalidResult << endl;
}
catch (const exception& e) {
cout << "Caught exception in main: " << e.what()
<< endl;
// Handle the exception at the highest level
}

return 0;
}

Output
Result: 20
Caught exception in divide(): Division by zero!
Caught exception in main: Division by zero!

Explanation:
 The program first calculates the sum of 10 and the result of dividing 20 by 2, which is
20. This result is printed and there are no exceptions raised in this part.
 Next, the program attempts to divide by zero when calculating the sum of 5 and the result
of dividing 10 by 0. This triggers a “Division by zero!” exception which is caught within
the divide() function and rethrown. The rethrown exception is then caught in the main()
function and is printed as “Division by zero!” along with the appropriate exception
handling messages.

The Power of Rethrowing Exceptions


Rethrowing exceptions in C++ has the following advantages advantages:
1. Exception Type Preservation
The preservation of exception handling in C++ is a feature. It enables catch blocks at levels to
effectively handle specific types of exceptions allowing for more precise error management.
2. Additional Processing
Additionally rethrowing exceptions provides the opportunity to perform operations or log extra
information about the exception before it is caught again further up the call stack. For example
you can add debugging details offer context or encapsulate the original exception within
another exception to provide more helpful information to higher level catch blocks.
3. Catching Exceptions by Reference
When rethrowing an exception it is crucial to catch it by reference (const std;;exception&)
rather than by value. This ensures that the exception object remains valid after being caught
and rethrown multiple times during the exception handling process.
4. Handling Nested Exceptions
C++ also allows for nested exceptions where one exception is raised inside the catch block of
another exception. If a nested exception is rethrown it becomes part of the exception as a
std;;nested_exception. This feature enables handling of outer and nested exceptions if
necessary.
5. Exception Propagation
Rethrowing exceptions allows them to propagate up the call stack until they are eventually
caught and handled by a catch block. Any function in the call stack can halt the propagation of
an exception by catching it and rethrowing it. This mechanism ensures that exceptions are
handled based on the context in which they arise. In C++ rethrowing exceptions is an approach
to effectively manage and handle them.
You can use exception handling in an controlled way to manage exceptions in your C++
programs. It gives you the ability to control how exceptions are handled preserve the types of
exceptions perform processing and effectively handle nested exceptions. By understanding and
utilizing the idea of exceptions you can write C++ programs that are more resilient and
dependable.

Stack Unwinding

https://www.youtube.com/watch?v=AYQtEaf79ps
Stack Unwinding is the process of removing function entries from function call stack at run
time. The local objects are destroyed in reverse order in which they were constructed.
Stack Unwinding is generally related to Exception Handling. In C++, when an exception
occurs, the function call stack is linearly searched for the exception handler, and all the entries
before the function with exception handler are removed from the function call stack. So,
exception handling involves Stack Unwinding if an exception is not handled in the same
function (where it is thrown). Basically, Stack unwinding is a process of calling the
destructors (whenever an exception is thrown) for all the automatic objects constructed at run
time.

// CPP Program to demonstrate Stack Unwinding


#include <iostream>
using namespace std;

// A sample function f1() that throws an int exception


void f1() throw(int)
{
cout << "\n f1() Start ";
throw 100;
cout << "\n f1() End ";
}

// Another sample function f2() that calls f1()


void f2() throw(int)
{
cout << "\n f2() Start ";
f1();
cout << "\n f2() End ";
}

// Another sample function f3() that calls f2() and handles


// exception thrown by f1()
void f3()
{
cout << "\n f3() Start ";
try {
f2();
}
catch (int i) {
cout << "\n Caught Exception: " << i;
}
cout << "\n f3() End";
}

// Driver Code
int main()
{
f3();

getchar();
return 0;
}
Output
f3() Start
f2() Start
f1() Start
Caught Exception: 100
f3() End

 When f1() throws exception, its entry is removed from the function call stack, because
f1() doesn’t contain exception handler for the thrown exception, then next entry in call
stack is looked for exception handler.
 The next entry is f2(). Since f2() also doesn’t have a handler, its entry is also removed
from the function call stack.
 The next entry in the function call stack is f3(). Since f3() contains an exception handler,
the catch block inside f3() is executed, and finally, the code after the catch block is
executed.
Note that the following lines inside f1() and f2() are not executed at all.

cout<<"\n f1() End "; // inside f1()


cout<<"\n f2() End "; // inside f2()

If there were some local class objects inside f1() and f2(), destructors for those local objects
would have been called in the Stack Unwinding process.

You might also like