Try_catch exceptions for C + +

Source: Internet
Author: User
Tags define function finally block readfile throw exception

Most of the content goes from: http://blog.csdn.net/codestinity/article/details/6877581

A simple example

First, a simple example is used to familiarize yourself with C + + Try/catch/throw:

1  #include  //contains header file
2  #include
3  doublefuc (double x, Doubley)  //define function
4  {
5 if (y==0)
6 {
7 THROW  y ;  //Divisor is 0, throws exception
8 }
9 returnx/y; //Otherwise returns two number of quotient
10 }
11  voidmain ()
12  {
13 double res;
14 try //Definition exception
15 {
16 res=fuc (2,3);
17 cout< The result of XY is res>< endlbr style= ' font-size:14px;font-style:normal;font-weight:normal; Font-family:simsun;color:rgb,/>18 res=fuc (4,0);  //exception
19 }
20 catch (double) //catch and handle exception
21 {
22 cerr< error of DIVIDINGZERONBR style= ' font-size:14px; Font-style:normal;font-weight:normal;font-family:simsun;color:rgb,/>23 exit (1);  // Exception exit program
24&NBSP;}
25 }

The data type of the catch needs to match the data type of the throw.

Second, catch (...) ) The role of

catch (...) Can capture a variety of data types of exception objects, so it provides programmers a better control of the exception object, so that the development of software systems have a good reliability. So a more experienced programmer would normally organize the code modules to write it, as follows:
void Func ()
{
Try
{
The program code here completes the really complex computational work that the code performs during the execution
It is possible to throw exception objects of type DataType1, DataType2, and DataType3.
}
catch (datatype1& D1)
{
}
catch (datatype2& D2)
{
}
catch (datatype3& D3)
{
}
Note The DataType1, DataType2, and DataType3 that may be thrown in the try block above three
The exception object of the type is already in front of the corresponding catch block to handle. But why
Also define a catch (...) at the end of the block? This is to have better security and
Reliability, avoiding the process caused by the above try block throwing out other exception objects that are not considered
The serious consequences of unexpected crashes, and this is particularly effective on systems developed with VC,
For catch (...) Can catch the system anomalies, and the system anomaly often makes the programmer headache, now
In the system is generally more complex, and by a lot of people jointly developed, accidentally will lead to a
The pointer variable points to other illegal areas, resulting in an unexpected disaster. catch (...) For this
Potential pitfalls provide an effective remedy.
catch (...)
{
}
}
Third, object-oriented processing in exception

First look at the following example:

Void OpenFile (string f)
{
Try
{
//Open file operation, may throw fileopenexception
}
catch (fileopenexception & Fe)
{
//Handle This exception, if the exception can be recovered well, then the function
//normal return after processing, otherwise you must re-throw this exception for the upper call function to be able to
//The exception object
int Result =reopenfile (f);
if (result = = false) throw;
}
}

void ReadFile (file f)
{
Try
{
//Read data from file, may throw filereadexception
}
catch ( filereadexception& Fe)
{
//Handle This exception, if the exception can be recovered well, then the function
//normal return after processing, otherwise you must re-throw this exception for the upper call function to be able to again
The exception object
int result =rereadfile (f);
if (result = = false) throw;
}
}

void WriteFile (file f)
{
Try
{
//to write data to file, may throw filewriteexception
}
catch ( filewriteexception& Fe)
{
//Handle This exception, if the exception can be recovered well, then the function
//normal return after processing, otherwise you must re-throw this exception, For the upper call function to be able to handle the exception object again
int result =rewritefile (f);
if (result== false) throw; 

}

void Func ()
{
Try
{
Operation of the file, may appear filewriteexception, filewriteexception
and filewriteexception anomalies
OpenFile (...);
ReadFile (...);
WriteFile (...);
}
Note: Fileexception are fileopenexception, filereadexception and Filewriteexception
, so the catch (FILEEXCEPTION&FE) defined here can capture all the different
Often.
catch (fileexception& Fe)
{
exceptioninfo* EF =fe. Getexceptioninfo ();
cout< fe endlbr style= ' Font-size:14px;font-style:normal;font-weight:normal;font-family:simsun;color:rgb (85, 85, ); '/>}
}

Here are more examples of object-oriented and exception-handling combinations:

#include
Class Exceptionclass

{
Char*name;
Public
Exceptionclass (const char* name= "DefaultName")
{
cout< constructname>< endlbr style= ' font-size:14px;font-style:normal;font-weight:normal;font-family: Simsun;color:rgb (/>this-<name=name;);
}
~exceptionclass ()
{
cout< destructname>< endlbr style= ' font-size:14px;font-style:normal;font-weight:normal;font-family: Simsun;color:rgb (in), '/>}
Voidmythrow ()
{
Throw Exceptionclass ("my Throw");
}
}

void Main ()

{
Exceptionclass E ("Test");
Try

{
E.mythrow ();
}
catch (...)
{
cout< endl>
}
}
Here is the output information:
Construct Test
Construct my Throw
Destruct my throw
****************
Destruct my throw (this is the destructor for the copy of the exception class in the exception handling space)
Destruct Test
======================================
However, in general, we may be more accustomed to the exception of the statement and to throw the exception class into different classes to write, the following code can be more willing to write:
Class Exceptionclass

{
Public
Exceptionclass (const char* name= "Exception Default Class")

{
cout< Exception Class constructstringendl>
}
~exceptionclass ()

{
cout< Exception Class destructstringendl>
}
void ReportError ()

{
cout< Exception Class this isreport Error messageendl>
}
};

Class Arguclass

{
char* name;
Public
Arguclass (char* name= "DefaultName")

{
cout< constructstringname>< endlbr style= ' font-size:14px;font-style:normal;font-weight:normal; Font-family:simsun;color:rgb (/>this-<name=name;);
}
~arguclass ()

{
cout< destructstringname>< endlbr style= ' font-size:14px;font-style:normal;font-weight:normal;font-family : Simsun;color:rgb (----); '/>}
void Mythrow ()

{
Throw Exceptionclass ("my Throw");
}
};

_tmain ()
{
Arguclass e ("haha");
Try

{
E.mythrow ();
}
catch (int)
{
cout< If This is a Message displayscreen this is aerrorendl>
}
catch (Exceptionclassptest)
{
Ptest.reporterror ();
}
catch (...)

{
cout< endl>
}
}
Output message:
Construct String::haha
Exception Class Construct String
Exception Class Destruct String
Exception Class:: This is the report Error Message
Exception Class Destruct String
Destruct String::haha

Iv. exception throws in construction and destruction
First look at a program, if I throw an exception where the constructor is, will the destructor of this class be called? But if it is not called, will not the things in that class be released?

#include
#include

Class ExceptionClass1
{
char* s;
Public
ExceptionClass1 ()

{
cout< exceptionclassendl>
S=NEWCHAR[4];
cout< Throwa exceptionendl>
THROW18;
}
~exceptionclass1 ()

{
cout< exceptionclassendl>
Delete[]s;
}
};

void Main ()

{
Try

{
ExceptionClass1 e;
}

catch (...)
{}
}

The result is:

ExceptionClass1 ()
Throw a exception

Between these two outputs, we have allocated memory to s, but the memory is not freed (because it was released in the destructor). This should be said to be true because the object is not fully constructed.

To avoid this, I think you might say that an object should be avoided by its own constructor involving exception throws. That is , neither an exception is thrown in the constructor, nor should an exception be thrown in everything that is called by the constructor.
But in C + + You can throw exceptions in constructors, and the classic solution is to use STL's standard class Auto_ptr.

So what happens in the destructor? We already know that after an exception is thrown, the destructor of itself is called, and if there is an exception thrown in the destructor, the existing exception has not been caught, causing the exception to be caught.

V. Standard C + + exception classes

Standard exceptions are derived from a common base class exception. The base class contains the necessary polymorphism functions to provide an exception description that can be overloaded. The following is a prototype of the exception class:

Class exception

{

Public

Exception () throw ();

Exception (const exception& RHS) throw ();

exception& operator= (constexception& rhs) throw ();

Virtual~exception () throw ();

Virtualconst Char *what () const throw ();

};

C + + has a number of standard exception classes:

Namespace Std

{

Exception derivation

Class logic_error;//logic error, can be detected before the program runs

Logic_error derivation

Classdomain_error; Violation of preconditions

Classinvalid_argument; Indicates an invalid argument to the function

Classlength_error; An attempt to indicate that there is an object exceeding the maximum size_t length of the type

Classout_of_range; Parameter out of bounds

Classbad_cast; There is an invalid dynamic_cast expression in run-time type recognition

Classbad_typeid; The report has a null pointer p in the expression test typeid (*p)

Exception derivation

Class runtime_error;//run-time error, only detected during program run

Runtime_error derivation

Classrange_error; Violation of post conditions

Classoverflow_error; Report an arithmetic overflow

Classbad_alloc; Storage Allocation error

}

The standard library exception class is defined in the following four header files

1. Exception header file: Defines the most common standard exception class, whose class name is exception. Only notifies the exception of the generation, but does not provide more information

2. stdexcept header file defines the following common exception classes

function function or effect

The most common problems of exception

Runtime_error Run-time error: Problem only detected at run time

Range_error Run-time error: The resulting result is beyond a meaningful range of domains

Overflow_error Run-time error: Calculation overflow

Underflow_error Run-time error: Calculating underflow

Logic_error Logic Error: Issues that can be detected before running

Domain_error logic Error: The result value of the parameter does not exist

Invalid_argument logic error: Inappropriate parameters

Length_error logic Error: Attempting to generate an object that exceeds the maximum length of the type

Out_of_range logic Error: Using a value beyond the valid range

3. The new header defines the Bad_alloc exception type, providing an exception that is thrown by new because it cannot allocate memory

4. type_info header file defines Bad_cast exception type (to use Type_info must contain TypeInfo header file)

The following are examples of using exception classes:

First, I define several exception classes, which can also be derived from standard exception classes, as follows

Class Badinitializers
{
Public
Badinitializers () {}
};

Class Outofbounds
{
Public
outofbounds (int i) {cout< sizei>< is Illegalendl >
};

Class Sizemismatch
{
Public
Sizemismatch () {}
};

Then to use throw to throw the exception class where needed in the program, two examples of thrown exception classes are as follows

Template
array1d::array1d (int sz)
{
if (sz<0 br style= ' Font-size:14px;font-style:normal;font-weight:normal;font-family:simsun;color:rgb (85, 85, 85); ' /> {

Throwbadinitializers ();

Throwinvalid_argument ("Size has been bigger than 0!!!");

}
Size=sz;
Element=new T[size];
}

Template
T&array1d::operator[] (inti) const
{
if (i<0 i>=size)
{

Throwoutofbounds (i);
}
return element[i];
}

Then use the Try...catch in the main program ... To catch the exception and handle it accordingly, as follows

Try

{
int i=0;
ARRAY1DA1 (5);
A1[0]=1;
a1[1]=3;
a1[2]=5;
a1[3]=7;
a1[4]=8;
ARRAY1DA2 (A1);
for (i=0;i
{
cout< ai>< br style= ' Font-size:14px;font-style:normal;font-weight:normal;font-family:simsun;color:rgb (85 , (/>);
cout< endl>

Array1da3 (5);
A3=A1+A2;
cout< a>
}
catch (Badinitializers)
{
cout< errorbadinitializersendl>
}
catch (Outofbounds &e)
{
cout< erroroutofboundsendl>
}
catch (Sizemismatch &e)
{
cout< errorsizemismatchendl>
}

catch (Invalid_argument&e)
{
cout< errorewhat>< endlbr style= ' Font-size:14px;font-style:normal;font-weight:normal;font-family:simsun; Color:rgb (255, 0, 0); '/>}
catch (...)
{
cout< Anunknown errorendl>
}

Six, try finally use

__try
{
FILE://Protection block
}
__finally
{
file://End Handler
}
In the preceding code snippet, the operating system and the compiler work together to ensure that the __f i n a l y code block in the end handler can be executed, regardless of how the protection body (T ry block) exits. The end handler (f i na l y block) is called whether you use R e t u r n in the protection body, or G o t o, or longjump.

Let's look at a real column: (return value: 10, no leak, performance cost: small)
DWORD Func_sehterminatehandle ()
{
DWORD dwreturndata = 0;
HANDLE Hsem = NULL;
Const char* Lpsemname = "Termsem";
Hsem = CreateSemaphore (NULL, N, Lpsemname);
__try
{
WaitForSingleObject (Hsem,infinite);
Dwreturndata = 5;
}
__finally
{
ReleaseSemaphore (Hsem,1,null);
CloseHandle (Hsem);
}
Dwreturndata + = 5;
return dwreturndata;
}
This code should just be a basic function, and we'll modify it later to see how the end handler works:
====================
Add a sentence in the code: (Return Value: 5, no leak, performance consumption: lower)
DWORD Func_sehterminatehandle ()
{
DWORD dwreturndata = 0;
HANDLE Hsem = NULL;
Const char* Lpsemname = "Termsem";
Hsem = CreateSemaphore (NULL, N, Lpsemname);
__try
{
WaitForSingleObject (Hsem,infinite);
Dwreturndata = 5;
Returndwreturndata;
}
__finally
{
ReleaseSemaphore (Hsem,1,null);
CloseHandle (Hsem);
}
Dwreturndata + = 5;
return dwreturndata;
}
Added a return statement at the end of the try block. This return statement tells the compiler to exit the function here and return the contents of the Dwtemp variable, which now has a value of 5. However, if the return statement is executed, the thread will not release the beacon and other threads will no longer be able to gain control of the beacon. As you can imagine, such an order of execution can cause a lot of problems, and those threads that wait on the beacon may never resume execution.
By using the end handler, you can avoid premature execution of the return statement.when the return statement attempts to exit the try block, the compiler ensures that the code in the finally block is first executed。 Make sure that the code in the finally block executes before the return statement in the try block exits. In the program, the ReleaseSemaphore call is placed in the end handler block to ensure that the beacon is always released. This will not cause a thread to always have a beacon, otherwise it would mean that all other threads waiting for the beacon will never be allocated CPU time.
after the code in the finally block executes, the function actually returns. Any code that appears below the finally block will no longer execute because the function is returned in the try block. So the return value of this function is 5, not 10.
The reader may want to ask how the compiler guarantees that the finally block executes before the try block can exit. When the compiler examines the source code, it sees a return statement in the try block. SuchThe compiler generates code to save the return value (in this case, 5) in a temporary variable established by the compiler. The compiler then generates code to execute the instructions contained in the fi n A l ly block, which is called a partial expansion。 In a more special case, the system executes the contents of the finally block because of code that exits prematurely in the try block, resulting in a partial expansion. After the instruction in the finally block is executed, the value of the compiler temporary variable is taken out and returned from the function.
As you can see, to accomplish these things, the compiler must generate additional code and the system will perform additional work.

Summary description of Finally block
We have made a clear distinction between the two cases of enforcing finally blocks:
• Enter the normal control flow of the finally block from the try block.
• Local expansion: Force control to the finally block from the early exit of the try block (Goto, longjump, continue, break, return, etc.).
In the third case, global unwind, this is seen later.

Vii. C + + exception parameter passing

Syntactically, declaring a parameter in a function is the same as declaring a parameter in a catch clause, a parameter in a catch can be a value type, a reference type, a pointer type. For example:
Try
{
.....
}
catch (A A)
{
}
catch (b& B)
{
}
catch (c* C)
{
}
Although the surface is the same, the compiler handles the two differently. When a function is called, control of the program is eventually returned to the function's call,but when an exception is thrown, control never returns to the place where the exception was thrown.。
Class A;
void Func_throw ()
{
A;
Throwa; A copy of a is thrown and copied to a temporary object.
}
Try
{
Func_throw ();
}
catch (a A)//copy of temporary object
{
}
when we throw an exception object, we throw a copy of the exception object. When the exception object is copied, the copy operation is done by the object's copy constructor. The copy constructor is a copy constructor of the class that corresponds to the static type (Statictype) of the object, rather than the copy constructor of the object's dynamic type (DynamicType) corresponding class. The object loses rtti information at this time.
An exception is a copy of another object that affects how you throw an exception in the catch block. such as the following two catch block, at first glance looks like:
catch (a& W)//Catch exception
{
Handling Exceptions
Throw Re-throw the exception and let it continue to pass
}
catch (a& W)//Catch Widget exception
{
Handling Exceptions
throw W; Passing copies of caught exceptions
}
The first chunk that is re-thrown is the current exception (currentexception), regardless of its type. (There may be a derived class of a)
The second catch block re-throws the new exception, losing the original type information.
In general, you should use throw to re-throw the current exception, because it does not change the type of exception that is passed out, and is more efficient because you do not need to generate a new copy.
Take a look at these three types of statements:
catch (A W) ...//pass value
catch (a& W) ...//by passing a reference, an object that is thrown by an exception (always a temporary object) can be captured by a normal reference
catch (const a& w) ...//const reference

Return to the copy of the exception object. We know that when passing the parameters of a function in a value-transfer way, we create a copy of the passed object and store the copy in the function's parameters. Also we do this when we pass an exception by passing a value, when we declare a catch clause like this:
catch (A W) ...//pass-through value capture
Two copies of the thrown object are created, one is a temporary object that all exceptions must have, and the second is to copy the temporary object into the W. In fact, the compiler optimizes a copy. Similarly, when we catch an exception by reference,
catch (a& W) ...//capture by reference
catch (const a& w) ...//const reference capture
This will still create a copy of the object being thrown: the copy is a temporary object. instead, when we pass a function argument by reference, there is no object copy. That being said, not all compilers do this.

Other than thatthrowing an exception through a pointer is the same as passing a parameter through a pointer. Either way, a copy of the pointer is passed. You cannot assume that the thrown pointer is a pointer to a local object because the local variable was freed when the exception left the local variable's living space. The catch clause obtains a pointer to an object that does not already exist. This behavior should be avoided at design time.
Another important difference is the process of matching the type between the caller of the function or the person who throws the exception and the callee or exception trap.when a function passes a parameter, if the argument does not match, then the compiler attempts a type conversion, if one exists. For exception handling, this is not the case at all. See the example:

void Func_throw ()
{
CStringA;
Throwa; A copy of a is thrown and copied to a temporary object.
}

Try
{
Func_throw ();
}
catch (const char* s)
{
}
The CString is thrown, and if it is captured with a const char*, it is not caught by this exception.
However, there are two types of conversions that can be made when an exception is matched in a catch clause. The first is the conversion of a base class to a derived class, aThe catch clause used to capture the base class can also handle exceptions of the derived class type. In turn, the exception that is used to catch a base class that is not captured by a derived class。
The second is to allow the conversion from a typed pointer (typed pointer) to an untyped pointer (untyped pointer), so a catch clause with a constvoid* pointer captures any type of pointer-type exception:
catch (const void*) ...//can catch all pointer exceptions
In addition, you can also use catch (...). To catch all exceptions, note that it is a three point.
The last difference between passing parameters and passing exceptions is that the catch clause match order always depends on the order in which they appear in the program。 Therefore, a derived class exception may be
The catch clause of the Richie class exception is caught, which is called an exception intercept, and the general compiler will have a warning.

Class A {
Public
A ()
{
Cout < class A creates Endlbr style= ' Font-size:14px;font-style:normal;font-weight:normal;font-family:simsun;color : RGB (----); '/>}
void print ()
{
cout < A endlbr style= ' Font-size:14px;font-style:normal;font-weight:normal;font-family:simsun;color:rgb (85, 85, ); '/>}
~a ()
{
cout < class A destruct endlbr style= ' Font-size:14px;font-style:normal;font-weight:normal;font-family:simsun; Color:rgb (the "/&gt");
};
Class B:public A
{
Public
B ()
{
cout < class B Create Endlbr style= ' Font-size:14px;font-style:normal;font-weight:normal;font-family:simsun;color: RGB (----); '/>}
void print ()
{
cout < B endlbr style= ' Font-size:14px;font-style:normal;font-weight:normal;font-family:simsun;color:rgb (85, 85, ); '/>}
~b ()
{
cout < class B destruct endlbr style= ' Font-size:14px;font-style:normal;font-weight:normal;font-family:simsun; Color:rgb (the "/&gt");
};
void Func ()
{
b b;
Throw B;
}
Try
{
Func ();
}
catch (b& B)//must put B in front, if put a in front, b in the back, then B type of exception will be intercepted first.
{
B.print ();
}
catch (a& A)
{
A.print ();
}

Try_catch exceptions for C + +

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.