3. Contents
• Few standard exceptions
• Namespaces
• using
• using namespace
• Preprocessor
• Preprocessor directives
• #include explained
4. Exception Handling - Introduction
• Exception handling is a mechanism that separates code
that detects and handles exceptional circumstances from
the rest of your program.
• Note that an exceptional circumstance is not necessarily
an error.
• An exception is a situation that would be unusual for the
program that is being processed.
• As a programmer, you should anticipate any abnormal
behavior that could be caused by the user entering
wrong information that could otherwise lead to
unpredictable results.
5. • An error result or an unpredictable behavior on
your program not caused by the operating
system but that occurs in your program is called
an exception.
• The ability to deal with a program’s eventual
abnormal behavior is called exception handling.
• Exceptions are run-time anomalies, such as
division by zero, that require immediate handling
when encountered by your program.
• Exceptions are run-time anomalies, such as
division by zero, that require immediate handling
when encountered by your program.
6. • With C++ exception handling, your
program can communicate unexpected
events to a higher execution context that
is better able to recover from such
abnormal events.
• These exceptions are handled by code
that is outside the normal flow of control.
• It could be in the same function that
generates it or outside the function.
7. • When a function detects an exceptional
situation, you represent this with an object.
This object is called an exception object.
• This exception object is actually thrown
when an exception case is encountered
• The handler code catches this exception
object and writes the appropriate code to
take a proper action to handle the case.
8. • During the execution of a program, the computer
will face two types of situations: those it is
prepared to deal with and those it doesn’t like.
• Imagine you write a program that asks the user
to supply two numbers to perform a calculation.
• This is a classic easy program. When it comes
up, the user is asked to simply type two
numbers; the program would use them to
perform a multiplication and display the result.
Here is such a program:
9. #include <iostream>
using namespace std;
int main() {
double a, b, c; // Request two numbers from the user
cout << "Please provide two numbersn"; cout << "First
Number: ";
cin >> a;
cout << "Second Number: ";
cin >> b;
// Multiply the numbers and display the result
c = a * b;
cout << "n" << a << " * " << b << " = " << c << "nn";
return 0;
}
10. • Imagine that a user, thanks to his infinite creativity or
because of just a mistake, decides to type the name of a
country or somebody’s telephone number as one of the
requested values.
• Since a program such as this one is not prepared to
multiply two strings or one number to a string (actually,
using operator overloading, you can tell the compiler how
to perform almost any type of operation on the values of
your program), it would not know what to do.
• Since a program such as this one is not prepared to
multiply two strings or one number to a string (actually,
using operator overloading, you can tell the compiler how
to perform almost any type of operation on the values of
your program), it would not know what to do.
11. • What actually happens is that, whenever the compiler is
handed a task, it would try to perform the assignment. If
it can’t perform the assignment, for any reason it is not
prepared for, it would throw an error.
• As a programmer, if you can anticipate the type of error
that could occur in your program, you can catch the error
yourself and deal with it by telling the compiler what to do
when this type of error occurs.
• As a programmer, you should anticipate any abnormal
behavior that could be caused by the user entering
wrong information that could otherwise lead to
unpredictable results.
12. • C++ provides mainly three keywords to handle an exception.
• Trying the normal flow: (try block)
• To deal with the expected behavior of a program, use the try
keyword as in the following syntax:
try {
normal code
that might generate an exception as well
}
• We must place a portion of code under exception
inspection.
• This is done by enclosing that portion of code in a try
block.
13. • It lets the compiler know that you are
anticipating an abnormal behavior and will
try to deal with it.
• The actual behavior that needs to be
evaluated is included between an opening
curly bracket “{“ and a closing curly
bracket “}”.
• Inside of the brackets, implement the
normal flow that the program should
follow, at least for this section of the code.
14. • Catching the exception: (catch block)
• During the flow of the program as part of the
try section, if an abnormal behavior occurs,
instead of letting the program crash or letting
the compiler send the error to the operating
system, you can transfer the flow of the
program to another section that can deal with
it.
• When an exceptional circumstance arises
within that block, an exception is thrown that
transfers the control to the exception handler
i.e. the catch block here.
15. A complete syntax of such code could be
try {
// the program flow
}
catch (Argument) {
// Catch the exception
}
• This section always follows the try section and
there must not be any code between the try’s
closing bracket and the catch section.
• The catch keyword is required and follows the
try section.
16. • The catch behaves a little like a function.
• It uses an argument that is passed by the
previous try section.
• The argument can be a regular variable or a
class.
• The behavior of the catch clause starts with an
opening curly bracket “{“ and ends with a closing
curly bracket “}”.
• The inside of the brackets is called the body of
the catch clause. Therefore, use the body of the
catch to deal with the error that was caused.
17. • Throw an error: (throw statement)
• An exception is thrown by using the
throw keyword from inside the try block.
• A throw expression accepts one
parameter which is passed as an
argument to the exception handler i.e.
the catch block
throw argument;
18. • We can also use a throw statement with
no argument as
throw;
19. // A simple Example - exceptions
#include <iostream>
using namespace std;
int main () {
try {
throw 20;
}
catch (int e) {
cout << "An exception occurred. Exception Nr. " << e << endl;
}
return 0;
}
20. • The code under exception handling is enclosed
in a try block.
• In this example this code simply throws an
exception:
throw 20;
• A throw expression accepts one parameter (in
this case the integer value 20), which is passed
as an argument to the exception handler catch
block.
catch (int e) {
cout << "An exception occurred. Exception Nr. " << e << endl;
}
21. A complete example
• Lets write a program that reads age of
student. It takes two actions after reading
the age
1. If the age > 0 that means it is a valid value,
the age value is printed back
2. If the age <=0 that means it is not a valid
value, it is an exceptional value and this
must be notified to the user.
In this case we throw an error saying the proper
message “ age should be grater than 0”
23. • If you run this program and type a positive integer for the
student’s age, the program would respond by displaying
the student age. That’s a good outcome.
• If you run the program and type a letter or any character,
the compiler would display the student age as 0. This is
the first proof that the compilers are already configured
to deal with some abnormal behavior of a program.
• If you enter the student age less than 0, then the throw
statement is executed, that means the control is
transferred to catch() block leaving rest of the statements
below throw without executing.
24. try {
…….
if (condition)
throw;
……. These statements
are not executed if When a throw statement
……. throw is executed. is encountered the control
} automatically transfers to
the catch block
catch(...) {
catch – statement1;
catch – statement2;
………..
}
25. Catching multiple exceptions
• The exceptions as we have seen so far
dealt with a single exception in a program.
• Most of the time, a typical program will
throw different types of errors.
• The C++ language allows you to include
multiple different catch blocks.
• Each catch block can face a specific case
for error handling.
26. Catching multiple exceptions
• Syntax for this could be as
try {
Code to Try
}
catch(Arg1) {
One Exception
}
catch(Arg2) {
Another Exception
}
27. The compiler would proceed in a top-down as follows:
• Following the normal flow control of the program, the compiler
enters the try block.
• If no exception occurs in the try block, the rest of the try block is
executed.
• If an exception occurs in the try block, the try displays a throw that
specifies the type of error that happened.
– The compiler gets out of the try block and examines the first catch
– If the first catch doesn’t match the thrown error, the compiler proceeds
with the next catch. This continues until the compiler finds a catch that
matches the thrown error.
– If one of the catches matches the thrown error, the body of that catch
block is executed and program executes further after the catch block as
a normal execution.
28. Default Handler – catch(…)
If no catch matches the thrown error, you have (or the
compiler has) two
alternatives.
– If there is no catch that matches the error (which
means that you didn’t provide a matching catch), the
compiler hands the program flow to the operating
system (which calls the terminate() function).
– Another alternative is to include a catch whose
argument is three periods:
catch(…).
29. • The catch(…) is used if no other catch,
provided there was another, matches the thrown
error.
• The catch(…), if included as part of a catch
clause, must always be the last catch, unless it
is the only catch of the clause.
• If we use an ellipsis (...) as the parameter of
catch, that handler will catch any exception no
matter what the type of the throw exception is.
This can be used as a default handler that
catches all exceptions not caught by other
handlers if it is specified at last.
30. try {
// code here
}
catch (int param) {
cout << "int exception";
}
catch (char param) {
cout << "char exception";
}
catch (...) {
cout << "default exception";
}
• In this case the last handler would catch any
exception thrown with any parameter that is
neither an int nor a char.
31. Exception specifications
• When declaring a function we can limit the exception type it might
directly or indirectly throw
• This can be done by appending a throw suffix to the function
declaration like:
float myfunction (char param) throw (int);
This declares a function called myfunction which takes one
argument of type char and returns an element of type float.
The only exception that this function might throw is an exception of
type int.
32. • When we use the throw keyword in the header
of a function, it indicates what kind of exceptions
that function may throw.
• Thus, any type that does not appear in the
throw() part of the header cannot and will not be
thrown by that function. This is called a
guarantee.
• In essence, you are making a promise to
everyone who uses your function that there is a
fixed list of exception types that your function
may throw, and that these are the only types that
need to be watched for in try blocks containing
your function.
33. // Example
void doSomething (int value)
throw( int, CustomException )
{
if( value > 5 ) {
throw CustomException( "An error occurred." );
}
else {
throw 18;
}
}
• Here we see that doSomething() is declared to be able to throw
two types of exceptions: integers and CustomExceptions. Other
functions who call this function now only need to write catch
blocks for these two data types, and nothing more. doSomething()
is promising that if it throws an exception, it will always be of one
of those two types.
34. • At times we need a function to handle all the
exceptions at its end only.
• That means no exception should pass through
the function and send to caller of the function.
• If throw specifier in function declaration is left
empty with no type, this means the function is
not allowed to throw exceptions
// no exceptions allowed
int myfunction (int param) throw();
35. • Similarly we may need to have a function that
can throw any possible exception type.
• Functions with no throw specifier (regular
functions) are allowed to throw exceptions with
any type:
// all exceptions allowed
int myfunction (int param);
Here the function myfunction() can through any
type of exception to its callers.
36. What can be thrown
• As I mentioned earlier, virtually any data type
in C++ can be thrown as an exception.
• For example, we could just as easily have
thrown an integer in our doSomething()
example:
void doSomething() {
throw 5;
}
37. • Or, we could have thrown, say, a boolean
value:
void doSomething() {
bool someVariable = false;
throw someVariable;
}
Here we are throwing a value of type bool in
c++.
38. Throw a class type
• Any data type in C++ can be thrown as an exception,
and this includes any custom data types we create.
• Remember, any data type in C++ can be thrown as an
exception, and this includes any custom data types we
create.
• Therefore, we can create classes to represent our
exceptions, and these classes can contain as much or
as little information as we like, structured however we
like.
39. // Define a class to handle custom exception
class CustomException {
private:
std::string message;
public:
CustomException( std::string message );
std::string getMessage() {
return message;
};
};
40. Here we have declared a simple class, CustomException.
• The class has one data member, message, which will
hold the error message associated with our exception.
We define a basic constructor that takes a string as an
argument to set the message, and we have an
accessor for message.
• Now, we can throw an instance of our
CustomException class as an exception and throw it in
a function like this:
// Use this class to throw as an exception
void doSomething() {
throw CustomException( "An error occurred." );
}
41. • At first, this seems no more useful than
throwing a lone string.
• The class even requires us to write more
code just to create the class!
• But look at the concept again. Now that
our exception is represented as an entire
object of our class rather than a primitive
or a string, we can add lots and lots of
information to our exception by adding
additional data members to our class.
43. Standard exceptions
• The C++ Standard library provides a base class
specifically designed to declare objects to be thrown as
exceptions.
• It is called exception and is defined in the <exception>
header file under the namespace std.
• This class has the usual default and copy constructors,
operators and destructors, plus an additional virtual
member function called what that returns a null-
terminated character sequence (char *) and that can be
overwritten in derived classes to contain some sort of
description of the exception.
44. Use exception class
• We can write a class myexception to represent our
exception using the class exception as:
// standard exceptions
#include <iostream>
#include <exception>
using namespace std;
class myexception: public exception {
virtual const char* what() const throw() {
return "My exception happened";
}
};
45. // This is how we can use myexception class
int main () {
myexception myex;
try {
throw myex;
}
catch (exception& e) {
cout << e.what() << endl;
}
return 0;
}
Output is::
exception happened.
46. • All exceptions thrown by components of the C+
+ Standard library throw exceptions derived
from this std::exception class. These are:
Exception Description
bad_alloc thrown by new on allocation failure
bad_cast thrown by new on allocation failure
bad_exception thrown when an exception type doesn't
match any catch
47. • For example, if we use the operator new and the
memory cannot be allocated, an exception of type
bad_alloc is thrown:
try {
int * myarray= new int[1000];
}
catch (bad_alloc&) {
cout << "Error allocating memory." << endl;
}
• It is recommended to include all dynamic memory
allocations within a try block that catches this type of
exception to perform a clean action instead of an
abnormal program termination, which is what happens
when this type of exception is thrown and not caught.
48. Namespaces
• Namespaces allow to group entities like
classes, objects and functions under a
name.
• This way the global scope can be divided
in "sub-scopes", each one with its own
name.
• This also allows us to use the same name
for more classes if they are in different
namespaces.
49. • The format of namespaces is:
namespace identifier
{
entities
}
• Where identifier is any valid identifier and
entities is the set of classes, objects and
functions that are included within the
namespace.
50. • For example
namespace myNamespace {
int a, b;
}
• In this case, the variables a and b are
normal variables declared within a
namespace called myNamespace.
51. Access entities from namespace
• In order to access these variables from outside
the namespace like myNamespace definced
here we have to use the scope operator ::.
• For example, to access the previous variables
from outside myNamespace we can write:
myNamespace::a;
myNamespace::b;
52. Namespace - Usage
• The functionality of namespaces is especially
useful in the case that there is a possibility that a
global object or function uses the same identifier
as another one, causing redefinition errors.
• In the example, there are two global variables
with the same name: var. One is defined within
the namespace first and the other one in
second. No redefinition errors happen thanks to
namespaces.
53. // namespaces
#include <iostream>
using namespace std;
namespace first {
int var = 5;
}
namespace second {
double var = 3.1416;
}
int main () {
cout << first::var << endl;
cout << second::var << endl;
return 0;
}
54. using – introduce names from a
namespace
• The keyword using is used to introduce a
name from a namespace into the current
declarative region.
• Lets declare two namespaces with names
as first and second. Both of them have two
variables named x and y.
55. // Example – using
#include <iostream>
using namespace std;
namespace first {
int x = 5;
int y = 10;
}
namespace second {
double x = 3.1416;
double y = 2.7183;
}
56. int main () {
using first::x;
using second::y;
cout << x << endl; // x is from first namespace
cout << y << endl; // y is from first namespace
cout << first::y << endl;
cout << second::x << endl;
return 0;
}
Output is
5
2.7183
10
3.1416
57. • Notice how in this code, x (without any
name qualifier) refers to first::x whereas y
refers to second::y, exactly as our using
declarations have specified.
• We still have to access first::y and
second::x using their fully qualified names,
as they are not specified by using
declaration.
58. using namespace
• The keyword using can also be used as a
directive to introduce an entire
namespace.
• By doing this, we can access any name
from that introduced namespace without
fully qualifier as ::.
• We can access the names from
introduced namespace by their names
directly.
59. // Example – using
#include <iostream>
using namespace std;
namespace first {
int x = 5;
int y = 10;
}
namespace second {
double x = 3.1416;
double y = 2.7183;
}
60. int main () {
using namespace first;
cout << x << endl;
cout << y << endl;
cout << second::x << endl;
cout << second::y << endl;
return 0;
}
Output is
5
2.7183
10
3.1416
61. • In this case, since we have declared that
we were using namespace first, all direct
uses of x and y without name qualifiers
were referring to their declarations in
namespace first.
• If we need to use the x and y of
namespace second, we should fully
qualify them using operator :: like
second::x
second::y
62. Scope of applying using
• using and using namespace have validity
only in the same block in which they are
stated
• or in the entire code if they are used
directly in the global scope.
63. // using namespace example
#include <iostream>
using namespace std;
namespace first {
int x = 5;
}
namespace second {
double x = 3.1416;
}
64. int main ()
{
// define a new block by {} and introduce first here
{
using namespace first;
cout << x << endl;
}
// define a new block by {} and introduce second here
{
using namespace second;
cout << x << endl;
}
return 0;
}
Output is:
5
3.1416
65. • In first block we only introduce first
namespace, that means x, y reffered there
will be of namespace first only.
• If we need to use the same of second
namespace we should fully qualify them
using ::
• Same explanation holds true for the
second block {} where namespace second
is introduced.
66. namespace alias
• A namespace alias is an alternative name
for a namespace.
• A namespace alias is a convenient way of
referring to a long namespace name by a
different, shorter name.
• It is an alternate names for existing
namespaces
67. namespace alias - syntax
• We can create an alias for a namespace as:
namespace new_name = current_name;
Example:
namespace INTERNATIONAL_BUSINESS_MACHINES
{
void f();
}
namespace IBM = INTERNATIONAL_BUSINESS_MACHINES;
• In this example, the IBM identifier is an alias for
INTERNATIONAL_BUSINESS_MACHINES. This is
useful for referring to long namespace identifiers.
68. an alias for a nested namespace
• An alias can also be applied to a nested namespace.
namespace INTERNATIONAL_BUSINESS_MACHINES
{
int j;
namespace NESTED_IBM_PRODUCT
{
void a() { j++; }
int j;
}
}
namespace NIBM =
INTERNATIONAL_BUSINESS_MACHINES::NESTED_IBM_PRODUCT
• In this example, the NIBM identifier is an alias for the namespace
NESTED_IBM_PRODUCT. This namespace is nested within the
INTERNATIONAL_BUSINESS_MACHINES namespace.
69. std namespace
• All the files in the C++ standard library
declare all of its entities within the std
namespace.
• That is why we have generally included
the using namespace std; statement in all
programs that used any entity defined in
iostream.
70. Preprocessor
• A unique feature of c language is the preprocessor. A program can
use the tools provided by preprocessor to make his program easy to
read, modify, portable and more efficient.
• Preprocessor is a program that processes the code before it passes
through the compiler. It operates under the control of preprocessor
command lines and directives.
• Preprocessor directives are placed in the source program before the
main line before the source code passes through the compiler it is
examined by the preprocessor for any preprocessor directives.
• If there is any appropriate actions are taken then the source
program is handed over to the compiler.
71. Preprocessor directives
• Preprocessor directives follow the special
syntax rules and begin with the symbol
#bin column1
• Notice that they do not require any
semicolon at the end like any other normal
statement
72. • A set of commonly used preprocessor
directives
#define Defines a macro substitution
#undef Undefines a macro
#include Specifies a file to be included
#ifdef Tests for macro definition
#endif Specifies the end of #if
#ifndef Tests whether the macro is not def
#if Tests a compile time condition
#else Specifies alternatives when # if test fails
73. File inclusion - #include
• The preprocessor directive #include can be used
to include any file in to your program if the
function s or macro definitions are present in an
external file they can be included in your file
#include “filename”
• In the directive the filename is the name of the
file containing the required definitions or
functions.
74. • Alternatively this directive can take the
form as below without double quotation
marks.
#include< filename >
• If used as above with filename within <>,
in this format the file will be searched in
only standard directories.