Pure Virtual Function

Download as pptx, pdf, or txt
Download as pptx, pdf, or txt
You are on page 1of 84

Pure Virtual Function

Introduction
• A pure virtual function is a virtual function in
C++ for which we need not to write any
function definition and only we have to
declare it. It is declared by assigning 0 in the
declaration.
• An abstract class is a class in C++ which have at least
one pure virtual function.
• Abstract class can have normal functions and
variables along with a pure virtual function.
• Abstract class cannot be instantiated, but pointers
and references of Abstract class type can be created.
• Abstract classes are mainly used for Upcasting, so
that its derived classes can use its interface.
• If an Abstract Class has derived class, they must
implement all pure virtual functions, or else they will
become Abstract too.
#include<iostream>
using namespace std;
class B

 public:    
  virtual void s() = 0; // Pure Virtual Function
};
class D:public B
{    public:       void s()
{     
cout << "Virtual Function in Derived class\n";      
}
};
int main()

 B *b;    
D dobj;    
b = &dobj;  
 b->s();
}
Virtual Function
• Virtual functions in C++ use to create a list of base class
pointers and call methods of any of the derived classes
without even knowing the kind of derived class object.
Virtual functions are resolved late, at the runtime.
• If A virtual function in a base class declared as once a
member function, it becomes virtual in every class
derived from that base class. So, use of the keyword
virtual is not necessary in the derived class while
declaring redefined versions of the virtual base class
function.
#include<iostream>
using namespace std;
class B

 public:      
virtual void s()
{    
 cout<<" In Base \n";    
 }
};
class D: public B

 public:    
  void s()
{    
 cout<<"In Derived \n";    
 }
};
int main(void)

 D d; // An object of class D  
 B *b= &d; // A pointer of type B* pointing to d  
 b->s(); // prints"D::s() called"  
 return 0;
}
OUTPUT:
In Base
In Derived
Abstract class
• An abstract class in C++ is a class that has at
least one pure virtual function (i.e., a function
that has no definition). The classes inheriting
the abstract class must provide a definition for
the pure virtual function; otherwise, the
subclass would become an abstract class itself.
• Abstract classes are essential to providing an
abstraction to the code to make it reusable
and extendable. For example, a Vehicle parent
class with Truck and Motorbike inheriting from
it is an abstraction that easily allows more
vehicles to be added. However, even though
all vehicles have wheels, not all vehicles have
the same number of wheels – this is where a
pure virtual function is needed.
Example
#include<iostream>
using namespace std;
class Shape
{ public:
virtual int Area() = 0; // Pure virtual function is declared as follows. // Function to set width.
void setWidth(int w)
{
width = w;
} // Function to set height.
void setHeight(int h)
{
height = h;
}
protected:
int width; int height;
}; // A rectangle is a shape; it inherits shape.
class Rectangle: public Shape
{
public: // The implementation for Area is specific to a rectangle.
int Area()
{
return (width * height);
}
}; // A triangle is a shape too; it inherits shape.
class Triangle: public Shape
{ public: // Triangle uses the same Area function but implements it to // return the area of a triangle.
int Area()
{
return (width * height)/2;
} };
int main()
{
Rectangle R;
Triangle T;
R.setWidth(5); R.setHeight(10); T.setWidth(20); T.setHeight(8); cout << "The area of the rectangle is: " << R.Area() << endl; cout << "The area of the triangle is: " << T.Area() << endl; }
Similarities between virtual function and pure
virtual function
• These are the concepts of Run-time
polymorphism.
• Prototype i.e. Declaration of both the
functions remains the same throughout the
program.
• These functions can’t be global or static.
Difference between virtual function and
pure virtual function in C++
Virtual function Pure virtual function

A pure virtual function is a member


function of base class whose only
A virtual function is a member function of
declaration is provided in base class and
base class which can be redefined by
derived class. should be defined in derived class
otherwise derived class also becomes
abstract.

Classes having virtual functions are not Base class containing pure virtual function
abstract. becomes abstract.
Syntax:

virtual<func_type><func_name>()
Syntax:virtual<func_type><func_name>()
{     = 0;
    // code
}

Definition is given in base class. No definition is given in base class.

Base class having pure virtual function


Base class having virtual function can be becomes abstract i.e. it cannot be
instantiated i.e. its object can be made.
instantiated.
Example Code
#include <iostream>
using namespace std;
class B

 public:      
virtual void s() //virtual function
{    
 cout<<" In Base \n";      
}
};
class D: public B
{  
public:      
void s()
{  
     cout<<"In Derived \n";      
}
};
int main(void)

 D d; // An object of class D    
B *b= &d;// A pointer of type B* pointing to d
b->s();// prints"D::s() called"  
 return 0;
}
Output
• In Derived
pure virtual function
#include<iostream>
using namespace std;
class B
{  
public:  
    virtual void s() = 0; // Pure Virtual Function
};
class D:public B

 public:    
  void s()
{     
cout << " Virtual Function in Derived class\n";       } };
int main()
{    B *b;  
 D dobj; // An object of class D  
 b = &dobj;// A pointer of type B* pointing to dobj  
 b->s();// prints"D::s() called"
}
OUTPUT
• Virtual Function in Derived class
Implications of polymorphic use of classes.

1. Declaring Destructor as Virtual


Manipulation of objects through pointers
require them to be created dynamically by using
new operator and later on delete them through
delete operator.
class A
{
Public: A()
cout << “BaseClass Constructor” <endl;
}
~A()
{
cout << “Base Class Destructor” < endl;
};
class B: public A
{
public: B()
{
cout << “Derived class constructor” << endl;
}
~B()
{
cout << “Derived class destructor” <<endl;
}
};
main()
{
A* a=new B;
delete a;
}
In the above example, a copy of derived class is
created in main() by using the new operator and
destroyed later on by using the delete operator.
The output of this program is as shown below,
Baseclass constructor
Derived class constructor
• The output is displayed based on the order in which the
constructors are called.

The output does not show the destructor of derived


class: This is because the derived class name is used with
new operator to call the constructor, so the compiler
created the specified object. The variable ‘a’ holds the
pointer to base class. When this variable is defined with
operator delete, the compiler could not predict that the
programmer wants to destroy the derived class instance.
This problem can be solved by declaring the destructor
of base class as virtual. Now the destructor gets invoked
through the virtual function table and the respective
destructor will be called.
virtual ~A()
{
cout << “Baseclass Destructor” <<endl;
}
The output of the program when the above code
is executed will be as shown below,
Base class constructor
Derived class constructor
Derived class destructor
Base class destructor.
Calling Virtual Functions in a Base class
Constructor
• The virtual functions may not work as
expected some times. The undesired output of
the virtual function call might result from the
base class constructor. This problem is
depicted by the below code,
class A
{
public: A()
{
cout << “Base class constructor calls clone()” <<endl;
clone();
}
virtual void clone()
{
cout<< “Base class clone() called” <<endl;
}
};
class B: public A
{
public: B()
{
cout << "Derived class constructor calls clone()" <<endl;
}
void clone()
{
cout << “Derived class clone() called” <<endl;
}
};
main()
{
B b;
A*a=&b;
cout << “Call to clone() through instance pointer” <<endl;
a→clone();
}
The output of above code is as follows:
Baseclass constructor calls clone()
Base class clone() called
Derived class constructor calls clone()
Call to clone() through instance pointer
Derived class clone() called
UNIT- 4
C++ I/O:
I/O using C functions
Stream classes hierarchy
Stream I/O
File Stream and String streams
Overloading operators
Error handling during file operations
Formatted I/O
C++ I/O
C++ I/O occurs in streams, which are sequences of bytes. If bytes flow
from a device like a keyboard, a disk drive, or a network connection
etc. to main memory, this is called input operation and if bytes flow
from main memory to a device like a display screen, a printer, a disk
drive, or a network connection, etc., this is called output operation.
I/O Library Header Files

<iostream>
This file defines the cin, cout, cerr and clog objects, which correspond to
1 the standard input stream, the standard output stream, the un-buffered
standard error stream and the buffered standard error stream,
respectively.
<iomanip>
2 This file declares services useful for performing formatted I/O with so-
called parameterized stream manipulators, such as setw and setprecision.
<fstream>
3
This file declares services for user-controlled file processing.
The Standard Output Stream (cout)
The predefined object cout is an instance of ostream class.
The cout object is said to be "connected to" the standard
output device, which usually is the display screen. The cout is
used in conjunction with the stream insertion operator,
which is written as << which are two less than signs
#include <iostream>
using namespace std; Output: Value of str is:
Hello C++
int main()
{
char str[] = "Hello C++";
cout << "Value of str is : " << str << endl; -printf(“Hello”);
}
The Standard Input Stream (cin)
• The predefined object cin is an instance of istream class. The cin object is
said to be attached to the standard input device, which usually is the
keyboard. The cin is used in conjunction with the stream extraction
operator, which is written as >> which are two greater than signs
#include <iostream>
using namespace std;
int main()
{
char name[50];
cout << "Please enter your name: ";
cin >> name;
cout << "Your name is: " << name << endl;
}
Output:
Please enter your name:
Keerthi
Your name is: Keerthi
The Standard Error Stream (cerr)
• The predefined object cerr is an instance of ostream class. The cerr
object is said to be attached to the standard error device, which is
also a display screen but the object cerr is un-buffered and each
stream insertion to cerr causes its output to appear immediately.
• The cerr is also used in conjunction with the stream insertion
operator
#include <iostream>
using namespace std;
int main()
{
char str[] = "Unable to read....";
cerr << "Error message : " << str << endl;
}
Output:
Error message : Unable to read....
The Standard Log Stream (clog)
• The predefined object clog is an instance of ostream class. The clog
object is said to be attached to the standard error device, which is
also a display screen but the object clog is buffered. This means that
each insertion to clog could cause its output to be held in a buffer
until the buffer is filled or until the buffer is flushed.
• The clog is also used in conjunction with the stream insertion
operator
#include <iostream>
using namespace std;
int main()
{
char str[] = "Unable to read....";
clog << "Error message : " << str << endl;
}
Output:
Error message: Unable to read
I/O refers to the input - output functions in C
language.
High level I/O
These are easily understood by human beings
The advantage is portability.
Low level I/O
These are easily understood by computer.
The advantage is that execution time is less.
The disadvantage is that Non portability.
cerr clog

It is an unbuffered standard It is a buffered standard


1. error stream error stream

2. It is used for displaying the It is used for logging.


error.

3. It is used to display the It can not display the


message immediately.  message immediately.

4. It can not store the It can store the message in


message to display it later. the buffer to display it later.

The “c” in cerr refers to The “c” in clog refers to


5. “character” and ‘err’ means “character” and ‘log’ refers
“error”, Hence cerr means to “logging”, hence clog
“character error”.  means “character logging”.

It is less efficient than clog It is more efficient than cerr


6. because it is unbuffered because it is buffered
output. output.

It is preferred for critical It is not preferred for


7. errors (errors that can critical errors (errors that
cause system crashes). can cause system crashes).
High level I/O Functions used in C

Function Description
fprintf ( ) write data into a file
fscanf ( ) read data from a file
putc ( )/ fputc() write a character into a file
getc ( ) /fgetc() read a character from a file
putw ( ) write a number into a file
getw ( ) read number from a file
fputs ( ) write a string into a file
fgets ( ) read a string from a file
fread() read an entire record from a file
fwrite() write an entire record into a file
Stream classes hierarchy
ios class is topmost class in the stream classes
hierarchy. It is the base class for istream,
ostream, and streambuf class.
 istream and ostream serves the base classes for
iostream class. The class istream is used for
input and ostream for the output. 
 Class ios is indirectly inherited to iostream class
using istream and ostream. To avoid the
duplicity of data and member functions of ios
class, it is declared as virtual base class when
inheriting in istream and ostream
class istream: virtual public ios
{
};
class ostream: virtual public ios
{
};
int main()
{
   A a;
   a.fun();
   return 0;
}
// C++ program to show that scope resolution operator :: is used
// to define a function outside a class
#include<iostream> 
using namespace std;  
class A 
{
public:   
   // Only declaration
   void fun_y();
};
  
// Definition outside class using ::
void A::fun_y()
{
   cout << "fun_y() called";
}
int main()
{
   A a;
   a.fun_y();
   return 0;
}
// Use of scope resolution operator in multiple inheritance.
#include<iostream>
using namespace std;
  
class A
{
protected:
    int x;
public:
    A() { x = 10; }
};
  
class B
{
protected:
    int x;
public:
    B() { x = 20; }
};
  
class C: public A, public B
{
public:
   void fun()
   {
      cout << "A's x is " << A::x;
      cout << "\nB's x is " << B::x;
   }
};  
int main()
{
    C c;
    c.fun();
    return 0;
}
Output:A's x is 10 B's x is 20
Stream IO
• 1.1  Streams
C/C++ IO are based on streams, which are sequence of
bytes flowing in and out of the programs (just like water
and oil flowing through a pipe). In input operations, data
bytes flow from an input source (such as keyboard, file,
network or another program) into the program. In output
operations, data bytes flow from the program to an
output sink (such as console, file, network or another
program). Streams acts as an intermediaries between the
programs and the actual IO devices, in such the way that
frees the programmers from handling the actual devices,
so as to archive device independent IO operations.
• C++ provides both the formatted and
unformatted IO functions. In formatted or
high-level IO, bytes are grouped and
converted to types such as int, double, string
or user-defined types. In unformatted or low-
level IO, bytes are treated as raw bytes and
unconverted. Formatted IO operations are
supported via overloading the stream
insertion (<<) and stream extraction (>>)
operators, which presents a consistent public
IO interface.
To perform input and output, a C++ program:
• Construct a stream object.
• Connect (Associate) the stream object to an actual
IO device (e.g., keyboard, console, file, network,
another program).
• Perform input/output operations on the stream,
via the functions defined in the stream's pubic
interface in a device independent manner. Some
functions convert the data between the external
format and internal format (formatted IO); while
other does not (unformatted or binary IO).
• Disconnect (Dissociate) the stream to the actual IO
device (e.g., close the file).
• Free the stream object.
Stringstream in C++

• A string stream associates a string object with a


stream allowing you to read from the string as if it
were a stream (like cin).
Basic methods are –
clear() — to clear the stream
str() — to get and set string object whose content is
present in stream.
operator << — add a string to the stringstream object.
operator >> — read something from the stringstream
object,
String stream class is extremely useful in parsing input.
EX: Count number of words in a
string
// CPP program to count words in a string using stringstream.
#include <bits/stdc++.h>
using namespace std;
int countWords(string str)
{
// breaking input into word using string stream
stringstream s(str); // Used for breaking words
string word; // to store individual words

int count = 0;
while (s >> word)
count++;
return count;
}

// Driver code
int main()
{
string s = "geeks for geeks geeks “;
cout << " Number of words are: " << countWords(s);
return 0;
}
• OUTPUT:
Input : geeks for geeks geeks
Output : Number of words are: 4
C++ FileStream example: writing to a file

• To read and write from a file we are using the


standard C++ library called fstream.
Data Type Description
fstream It is used to create files, write information
to files, and read information from files.
ifstream It is used to read information from files.
ofstream It is used to create files and write
information to the files.
#include <iostream>  
#include <fstream>  
using namespace std;  
int main () {  
  ofstream filestream("testout.txt");  
  if (filestream.is_open())  
  {  
    filestream << "Welcome to javaTpoint.\n";  
    filestream << "C++ Tutorial.\n";  
    filestream.close();  
  }  
  else 
cout <<"File opening is fail.";  
  return 0;  
}  
Example: reading from a file
#include <iostream>  
#include <fstream>  
using namespace std;  
int main () {  
  string srg;  
  ifstream filestream("testout.txt");  
  if (filestream.is_open())  
  {  
    while ( getline (filestream,srg) )  
    {  
      cout << srg <<endl;  
    }  
    filestream.close();  
  }  
  else {  
      cout << "File opening is fail."<<endl;   
    }  
  return 0;  
}  
C++ Read and Write Example
#include <fstream>  
#include <iostream>  
using namespace std;  
int main () {  
   char input[75];  
   ofstream os;  
   os.open("testout.txt");  
   cout <<"Writing to a text file:" << endl;  
   cout << "Please Enter your name: ";   
   cin.getline(input, 100);  
   os << input << endl;  
   cout << "Please Enter your age: ";   
   cin >> input;  
   cin.ignore();  
   os << input << endl;  
   os.close();  
   ifstream is;   
   string line;  
   is.open("testout.txt");   
   cout << "Reading from a text file:" << endl;   
   while (getline (is,line))  
   {  
   cout << line << endl;  
   }      
   is.close();  
   return 0;  
}  
• Output:
Writing to a text file:
Please Enter your name: Nakul Jain
Please Enter your age: 22
Reading from a text file: Nakul Jain 22
Overloading Operators
In C++, stream insertion operator “<<” is used for
output and extraction operator “>>” is used for input. 
We must know the following things before we start
overloading these operators. 
1) cout is an object of ostream class and cin is an
object of istream class 
2) These operators must be overloaded as a global
function. And if we want to allow them to access
private data members of the class, we must make
them friend. 
Why these operators must be overloaded as
global? 
In operator overloading, if an operator is overloaded as a member, then
it must be a member of the object on the left side of the operator. For
example, consider the statement “ob1 + ob2” (let ob1 and ob2 be
objects of two different classes).
To make this statement compile, we must overload ‘+’ in a class of ‘ob1’
or make ‘+’ a global function. 
The operators ‘<<‘ and ‘>>’ are called like ‘cout << ob1’ and ‘cin >> ob1’.
So if we want to make them a member method, then they must be
made members of ostream and istream classes, which is not a good
option most of the time. Therefore, these operators are overloaded as
global functions with two parameters, cout and object of user-defined
class.
#include <iostream>
using namespace std;
class Distance
{
private: int feet; // 0 to infinite
int inches; // 0 to 12
public: // required constructors
Distance()
{
feet = 0;
inches = 0;
}
Distance(int f, int i)
{
feet = f; inches = i;
}
friend ostream &operator<<( ostream &output, const Distance &D )
{
output << "F : " << D.feet << " I : " << D.inches;
return output;
}
friend istream &operator>>( istream &input, Distance &D )
{
input >> D.feet >> D.inches;
return input;
} };
int main()
{
Distance D1(11, 10), D2(5, 11), D3;
cout << "Enter the value of object : " << endl; cin >> D3;
cout << "First Distance : " << D1 << endl;
cout << "Second Distance :" << D2 << endl;
cout << "Third Distance :" << D3 << endl;
return 0;
}
Error handling during file operations

It is quite common that errors may occur while


reading data from a file in C++ or writing data to a file.
For example, an error may arise due to the following:
• When trying to read a file beyond indicator.
• When trying to read a file that does not exist.
• When trying to use a file that has not been opened.
• When trying to use a file in an inappropriate mode
i.e., writing data to a file that has been opened for
reading.
• When writing to a file that is write-protected i.e.,
trying to write to a read-only file.
Below are some Error handling functions
during file operations in C/C++:
1. ferror():
• In C/C++, the library function ferror() is used to check
for the error in the stream. Its prototype is written as:
int ferror (FILE *stream);
The ferror() function checks for any error in the stream.
It returns a value zero if no error has occurred and a
non-zero value if there is an error. The error indication
will last until the file is closed unless it is cleared by the
clearerr() function. 
Below is the program to implement the use
of ferror():
// C++ program to illustrate the use of ferror()
#include <bits/stdc++.h>
// Driver Code
int main()
{
FILE* fp;

// If a file is opened which does


// not exist, then it will be an
// error and corresponding errno
// value will be set
char feedback[100];

int i;
fp = fopen("GeeksForGeeks.TXT", "w");

if (fp == NULL) {
printf("\n The file could "
"not be opened");
exit(1);
}

printf("\n Provide feedback on "


"this article: ");
fgets(feedback, 100, stdin);

for (i = 0; i < feedback[i]; i++)


fputc(feedback[i], fp);

// Error writing file


if (ferror(fp)) {
printf("\n Error writing in file");
exit(1);
}

// Close the file pointer


fclose(fp);
}
2. clearerr():
• The function clearerr() is used to clear the end-of-
file and error indicators for the stream. Its
prototype can be given as:
void clearerr(FILE *stream);
The clearerr() clears the error for the stream pointed
by the stream. The function is used because error
indicators are not automatically cleared. Once the
error indicator for a specific stream is set, operations
on the stream continue to return an error value until
clearerr(), fseek(), fsetpos(), or rewind() is called.
Below is the program to implement the use
of clearerr():
// C++ program to illustrate the use of clearerr()
#include <bits/stdc++.h>
// Driver Code
int main()
{
FILE* fp;
char feedback[100];

char c;

fp = fopen("file.txt", "w");

c = fgetc(fp);
if (ferror(fp)) {
printf("Error in reading from"
" file : file.txt\n");
}
clearerr(fp);

if (ferror(fp)) {
printf("Error in reading from "
"file : file.txt\n");
}

// close the file


fclose(fp);
}
• The function perror() stands for print error. In
case of an error, the programmer can
determine the type of error that has occurred
using the perror() function. When perror() is
called, then it displays a message describing
the most recent error that occurred during a
library function call or system call. Its
prototype can be given as:
void perror (char*msg);
// C++ program to illustrate the use of perror()
#include <bits/stdc++.h>
#include <errno.h>

// Driver Code
int main()
{
FILE* fp;

// First rename if there is any file


rename("file.txt", "newfile.txt");

// Now try to open same file


fp = fopen("file.txt", "r");

if (fp == NULL) {

perror("Error: ");
return (-1);
}

// Close the file pointer


fclose(fp);

return (0);
}
Formatted I/O

• C++ helps you to format the I/O operations like


determining the number of digits to be displayed after
the decimal point, specifying number base etc.
Example:
• If we want to add + sign as the prefix of out output, we
can use the formatting to do so:
stream.setf(ios::showpos) If input=100, output will be
+100
• If we want to add trailing zeros in out output to be
shown when needed using the formatting:
stream.setf(ios::showpoint) If input=100.0, output
will be 100.000
There are two ways to do so:
• Using the ios class or various ios member functions.
• Using manipulators(special functions)
Formatting using the ios members:
• The stream has the format flags that control the
way of formatting it means Using this setf function,
we can set the flags, which allow us to display a
value in a particular format. The ios class declares a
bitmask enumeration called fmtflags in which the
values(showbase, showpoint, oct, hex etc) are
defined. These values are used to set or clear the
format flags.
Few standard ios class functions are:
• width(): The width method is used to set the
required field width. The output will be displayed
in the given width
• precision(): The precision method is used to set
the number of the decimal point to a float value
• fill(): The fill method is used to set a character to
fill in the blank space of a field
• setf(): The setf method is used to set various flags
for formatting output
• unsetf(): The unsetf method is used To remove
the flag setting
#include<bits/stdc++.h>
using namespace std; // The width() function defines width of the next value to be displayed in the output at the console.
void IOS_width()
{
cout << "--------------------------\n";
cout << "Implementing ios::width\n\n";
char c = 'A'; // Adjusting width will be 5.
cout.width(5);
cout << c <<"\n";
int temp = 10; // Width of the next value to be displayed in the output will not be adjusted to 5 columns.
cout<<temp;
cout << "\n--------------------------\n";
}
void IOS_precision()
{
cout << "\n--------------------------\n";
cout << "Implementing ios::precision\n\n";
cout << "Implementing ios::width";
cout.setf(ios::fixed, ios::floatfield);
cout.precision(2);
cout<<3.1422;
cout << "\n--------------------------\n";
}// The fill() function fills the unused white spaces in a value (to be printed at the console), with a character of choice.
void IOS_fill()
{
cout << "\n--------------------------\n";
cout << "Implementing ios::fill\n\n";
char ch = 'a'; // Calling the fill function to fill the white spaces in a value with a character our of choice.
cout.fill('*');
cout.width(10);
cout<<ch <<"\n";
int i = 1; // Once you call the fill() function, you don't have to call it again to fill the white space in a value with the same character.
cout.width(5);
cout<<i;
cout << "\n--------------------------\n";
}

void IOS_setf()
{
cout << "\n--------------------------\n";
cout << "Implementing ios::setf\n\n";
int val1=100,val2=200;
cout.setf(ios::showpos);
cout<<val1<<" "<<val2;
cout << "\n--------------------------\n";
}

void IOS_unsetf()
{
cout << "\n--------------------------\n";
cout << "Implementing ios::unsetf\n\n";
cout.setf(ios::showpos|ios::showpoint);
// Clear the showflag flag without
// affecting the showpoint flag
cout.unsetf(ios::showpos);
cout<<200.0;
cout << "\n--------------------------\n";
}

// Driver Method
int main()
{
IOS_width();
IOS_precision;
IOS_fill();
IOS_setf();
IOS_unsetf();
return 0;
}
Formatting using Manipulators
The second way you can alter the format
parameters of a stream is through the use of
special functions called manipulators that can be
included in an I/O expression.
UNIT - 5
• Exception Handling:
Benefits of exception handling
Throwing an exception
The try Block
Catching an exception
Exception objects
Exception specification
Stack unwinding
Rethrowing an exception
Catching all exception
Exception Handling
Exceptions are run-time anomalies or abnormal conditions
that a program encounters during its execution. There are
two types of exceptions: a)Synchronous,
b)Asynchronous(Ex:which are beyond the program’s control,
Disc failure etc). C++ provides following specialized
keywords for this purpose.
try: represents a block of code that can throw an exception.
catch: represents a block of code that is executed when a
particular exception is thrown.
throw: Used to throw an exception. Also used to list the
exceptions that a function throws, but doesn’t handle itself.
Why Exception Handling? 
Following are main advantages of exception
handling over traditional error handling:
1) Separation of Error Handling code from
Normal Code
2) Functions/Methods can handle any exceptions
they choose
3) Grouping of Error Types
Benefits of exception handling

The benefits of exception handling are as


follows, 
• (a) Exception handling can control run time
errors that occur in the program. 
• (b) It can avoid abnormal termination of the
program and also shows the behavior of
program to users. 
Exception Handling Keywords

• throw– when a program encounters a problem, it


throws an exception. The throw keyword helps the
program perform the throw.
• catch– a program uses an exception handler to catch
an exception. It is added to the section of a program
where you need to handle the problem. It’s done
using the catch keyword.
• try– the try block identifies the code block for which
certain exceptions will be activated. It should be
followed by one/more catch blocks.
The try/catch takes this syntax:
try
{ // the protected code
}
catch( Exception_Name exception1 )
{ // catch block
}
catch( Exception_Name exception2 )
{ // catch block
}
catch( Exception_Name exceptionN )
{ // catch block
}
Example
#include <iostream>
using namespace std;
int main()
{
int x = -1;

// Some code
cout << "Before try \n";
try {
cout << "Inside try \n";
if (x < 0)
{
throw x;
cout << "After throw (Never executed) \n";
}
}
catch (int x ) {
cout << "Exception Caught \n";
}

cout << "After catch (Will be executed) \n";


return 0;
}
Exception Objects
The exception object holds the error information about the exception that had occurred. The
information includes the type of error i.e., logic error or run time error and state of the program
when the error occurred. An exception object is created as soon as exception occurs and it is passed
to the corresponding catch block as a parameter. This catch block contains the code to catch the
occurred exception. It uses the methods of exception object for handling the exceptions. 
Syntax 
try 
{
throw exception object; 
}
catch (Exception &exceptionobject) 
{
}
To retrieve the message attached to the exception, exception object uses a method called what ().
This method returns the actual messages.
Syntax for what () Method
• exceptionobject.what();
Program
#include <iostream> 
#include <exception> 
using namespace std; 
class MyException : public exception 
{
public: 
const char * what() const throw() 
{
return" divide by zero exceptionl\n"; 
}
}; 
int main() 
{
try 
{
int x, y; 
cout << "Enter the two numbers :. \n"; 
cin>>x>>y; 
if(y==0) 
{
MyException z; 
throw z;
}
else 
{
cout <<"x/y =" <<x/y << endl; 
}
}
catch(exception &e) 
{
cout<<e.what();
}
• }
Exception Specification
Exception specifications are a C++ language
feature that indicate the programmer's intent
about the exception types that can be
propagated by a function. You can specify that a
function may or may not exit by an exception by
using an exception specification. The compiler
can use this information to optimize calls to the
function, and to terminate the program if an
unexpected exception escapes the function.
The dynamic exception specification, or throw(optional_type_list)
specification, was deprecated in C++11 and removed in C++17,
except for throw(), which is an alias for noexcept(true). This
exception specification was designed to provide summary
information about what exceptions can be thrown out of a
function, but in practice it was found to be problematic. The one
dynamic exception specification that did prove to be somewhat
useful was the unconditional throw() specification. For example,
the function declaration:
void MyFunction(int i) throw();
tells the compiler that the function does not throw any exceptions.
However, in /std:c++14 mode this could lead to undefined behavior
if the function does throw an exception. Therefore we recommend
using the noexcept operator instead of the one above:
void MyFunction(int i) noexcept;
Exception specifiction
Gives the details about what kind of exception a
function can throw
Sy: return_type fun_name(para_list)
throw(type1, type2,….)
{
//body of funtion
}
// exception_specification
#include<bits/stdc++.h>
using namespace std;
void add() throw(int,float) // exception specification
{
int a=10,b=0;
if(a==10||b==0)
{
throw 100,12.8; //throw integer type of exception /// throw 12.98
}
cout<<“addition is :”<<a+b;
}
int main()
{
try
{
add();
}
catch(int i)
{
cout<<“exception caught\n”;
}
}
Stack unwinding
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. 
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. 
Example
// 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;
}
Rethrowing an exception
Rethrowing an expression from within an
exception handler can be done by calling throw,
by itself, with no exception. This causes current
exception to be passed on to an outer try/catch
sequence. An exception can only be rethrown
from within a catch block. When an exception is
rethrown, it is propagated outward to the next
catch block.
Example
• #include<iostream>
using namespace std;
void sub(int i,int j)
{
    try
    {
        if(i==0)
        {
            throw i;
        }
        else
            cout<<“Subtraction result is: “<<i-j<<endl;
    }
    catch(int i)
    {
        cout<<“Exception caught inside sub()\n”;
        throw;
    }
};
int main()
{
    try
    {
        sub(8,4);
        sub(0,8);
    }
    catch(int k)
    {
        cout<<“Exception caught inside main()\n”;
    }
    return 0;
}
• OUTPUT:
• Subtraction result is: 4
Exception caught inside sub()
Exception caught inside main()
Catching all exceptions
• Exceptions are the problems which arise at the
time of execution of program. It is an event which
is thrown at runtime. It protects the code and run
the program even after throwing an exception.
Exception handling is used to handle the
exceptions. We can use try catch block to protect
the code.
• Catch block is used to catch all types of exception.
The keyword “catch” is used to catch exceptions.
#include <iostream>
using namespace std;
void func(int a)

 try
{   
if(a==0) throw 23.33;      
if(a==1) throw 's';
   }
catch(...)
{   
cout << "Caught Exception!\n";  
 }
}
int main()

 func(0);  
 func(1);  
 return 0;
}
Output:
Caught Exception!
Caught Exception!

You might also like