F6dc1 session6 c++

75
1 Course Name- B Sc Subject Name - C++ Semester - II Neetu Gupta

description

 

Transcript of F6dc1 session6 c++

Page 1: F6dc1 session6 c++

1

Course Name- B Sc

Subject Name - C++

Semester - II

Neetu Gupta

Page 2: F6dc1 session6 c++

Contents

• Exception – Introduction

• Exception handling

• Try, catch

• Throw

• Exception specification

• Custom exceptions

• Using exception class

Page 3: F6dc1 session6 c++

Contents

• Few standard exceptions

• Namespaces

• using

• using namespace

• Preprocessor

• Preprocessor directives

• #include explained

Page 4: F6dc1 session6 c++

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.

Page 5: F6dc1 session6 c++

• 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.

Page 6: F6dc1 session6 c++

• 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.

Page 7: F6dc1 session6 c++

• 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.

Page 8: F6dc1 session6 c++

• 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:

Page 9: F6dc1 session6 c++

#include <iostream> using namespace std; int main() {

double a, b, c; // Request two numbers from the user cout << "Please provide two numbers\n"; 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 << "\n\n"; return 0;

}

Page 10: F6dc1 session6 c++

• 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.

Page 11: F6dc1 session6 c++

• 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.

Page 12: F6dc1 session6 c++

• C++ provides mainly three keywords to handle an exception.

1. 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 codethat 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.

Page 13: F6dc1 session6 c++

• 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.

Page 14: F6dc1 session6 c++

2. 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.

Page 15: F6dc1 session6 c++

A complete syntax of such code could betry {

// 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.

Page 16: F6dc1 session6 c++

• 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.

Page 17: F6dc1 session6 c++

3. 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;

Page 18: F6dc1 session6 c++

• We can also use a throw statement with no argument as

throw;

Page 19: F6dc1 session6 c++

// 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;

}

Page 20: F6dc1 session6 c++

• 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;

}

Page 21: F6dc1 session6 c++

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”

Page 22: F6dc1 session6 c++

#include <iostream> using namespace std; int main() {

int StudentAge; cout << "Student Age: "; cin >> StudentAge;

try { if( StudentAge < 0)

throw “Positive Number required”; cout << "\n Student Age: " << StudentAge << "\n\n";

} catch( const char* str ) {

cout << "\n” << str << "\n \n";

}

cout << "\n"; return 0;

}

Page 23: F6dc1 session6 c++

• 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.

Page 24: F6dc1 session6 c++

try { …….if (condition)

throw;…….…….

} catch(...) {

catch – statement1;catch – statement2;………..

}

When a throw statement is encountered the control automatically transfers to the catch block

These statements are not executed if throw is executed.

Page 25: F6dc1 session6 c++

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.

Page 26: F6dc1 session6 c++

Catching multiple exceptions

• Syntax for this could be astry {

Code to Try

}

catch(Arg1) {

One Exception

}

catch(Arg2) {

Another Exception

}

Page 27: F6dc1 session6 c++

The compiler would proceed in a top-down as follows:

1. Following the normal flow control of the program, the compiler enters the try block.

2. If no exception occurs in the try block, the rest of the try block is executed.

3. If an exception occurs in the try block, the try displays a throw that specifies the type of error that happened.

a. The compiler gets out of the try block and examines the first catch b. 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.

c. 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.

Page 28: F6dc1 session6 c++

If no catch matches the thrown error, you have (or the compiler has) two

alternatives. i. 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).

ii. Another alternative is to include a catch whose argument is three periods:

catch(…).

Default Handler – catch(…)

Page 29: F6dc1 session6 c++

• 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.

Page 30: F6dc1 session6 c++

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.

Page 31: F6dc1 session6 c++

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.

Page 32: F6dc1 session6 c++

• 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.

Page 33: F6dc1 session6 c++

// Examplevoid 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.

Page 34: F6dc1 session6 c++

• 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();

Page 35: F6dc1 session6 c++

• 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 allowedint myfunction (int param);

Here the function myfunction() can through any type of exception to its callers.

Page 36: F6dc1 session6 c++

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; }

Page 37: F6dc1 session6 c++

• 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++.

Page 38: F6dc1 session6 c++

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.

Page 39: F6dc1 session6 c++

// Define a class to handle custom exceptionclass CustomException { 

private:         std::string message;

  public:     CustomException( std::string message );     std::string getMessage() {

return message; };

};

Page 40: F6dc1 session6 c++

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 exceptionvoid doSomething() {      throw CustomException( "An error occurred." ); }

Page 41: F6dc1 session6 c++

• 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.

Page 42: F6dc1 session6 c++

class CustomException {

private:     string message;     int errorCode;     bool fatal;   public:

CustomException( string message ); string getMessage() { return message;

};

int getErrorCode() { return errorCode;

};

bool isFatal() { return fatal;

};  };

Page 43: F6dc1 session6 c++

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.

Page 44: F6dc1 session6 c++

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";

} };

Page 45: F6dc1 session6 c++

// This is how we can use myexception classint main () {

myexception myex;try {

throw myex; } catch (exception& e) {

cout << e.what() << endl; } return 0;

}

Output is:: exception happened.

Page 46: F6dc1 session6 c++

• 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

Page 47: F6dc1 session6 c++

• 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.

Page 48: F6dc1 session6 c++

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.

Page 49: F6dc1 session6 c++

• 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.

Page 50: F6dc1 session6 c++

• For example

namespace myNamespace {

int a, b;

}

• In this case, the variables a and b are normal variables declared within a namespace called myNamespace.

Page 51: F6dc1 session6 c++

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;

Page 52: F6dc1 session6 c++

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.

Page 53: F6dc1 session6 c++

// 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;

}

Page 54: F6dc1 session6 c++

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.

Page 55: F6dc1 session6 c++

// 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;

}

Page 56: F6dc1 session6 c++

int main () { using first::x; using second::y; cout << x << endl; // x is from first namespacecout << y << endl; // y is from first namespacecout << first::y << endl; cout << second::x << endl; return 0;

}

Output is5 2.7183 10 3.1416

Page 57: F6dc1 session6 c++

• 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.

Page 58: F6dc1 session6 c++

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.

Page 59: F6dc1 session6 c++

// 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;

}

Page 60: F6dc1 session6 c++

int main () { using namespace first; cout << x << endl; cout << y << endl; cout << second::x << endl; cout << second::y << endl; return 0;

}

Output is5 2.7183 10 3.1416

Page 61: F6dc1 session6 c++

• 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::xsecond::y

Page 62: F6dc1 session6 c++

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.

Page 63: F6dc1 session6 c++

// using namespace example

#include <iostream>

using namespace std;

namespace first {

int x = 5;

}

namespace second {

double x = 3.1416;

}

Page 64: F6dc1 session6 c++

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

Page 65: F6dc1 session6 c++

• 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.

Page 66: F6dc1 session6 c++

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

Page 67: F6dc1 session6 c++

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.

Page 68: F6dc1 session6 c++

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.

Page 69: F6dc1 session6 c++

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.

Page 70: F6dc1 session6 c++

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.

Page 71: F6dc1 session6 c++

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

Page 72: F6dc1 session6 c++

• 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

Page 73: F6dc1 session6 c++

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.

Page 74: F6dc1 session6 c++

• 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.

Page 75: F6dc1 session6 c++

Thank You

75