The Complete Resource for All Web Builders
home account info subscribe login search FAQ/help site map contact us


 
Brief Full
 Advanced
      Search
 Search Tips
[an error occurred while processing this directive]
Previous Table of Contents Next


The next line declares an integer to hold the handle associated with the file to be opened. Notice that the dbOpen() function returns a non-zero, positive value to indicate success. The logic of this function call and the logic of the previous one are not consistent with each other.

The if statement that follows checks that the return from dbOpen() is greater than zero; otherwise, the associated else displays an error message.

The first line in this if block declares an array of char named data. This variable is used by the function call within the if statement that follows:

if( dbGetData( 1, data ) == DB_OK )

This example prints out the value of the variable as a result of the function call. A real database application might perform some operations on the data, expanding the if code block. Notice that the associated else displays an error to the user if the function call is unsuccessful.

The next if block makes a function call to close the data file. If the close is unsuccessful, an error message is displayed to the user.

Take one more look at the previous block of code. All it does is simply initialize, open, retrieve from, and close a data file. A lot of “extra” code is lying around taking up space, wouldn’t you say? Notice that the code always has to take one route if the function call is successful and another route if the function call fails for any reason. This tends to clutter the source code with a never-ending string of if-else statements. Another option is to use a global status variable, but this does not cut down on the if-else dilemma. As a matter of fact, this method tends to make the code look worse because you have to make the function call and then check the status variable.

Okay, let’s move on to the next section of code:

try {
    char data[ 30 ] = “” ;

    dbInitEH( ) ;
    int theHandle = dbOpenEH( “test.dat” ) ;

    dbGetDataEH( 1, data ) ;
    cout << “Data is: ” << data << endl ;
    dbCloseEH( theHandle ) ;
}
catch( int v ) {
    cout << “Error with DB: ” << v << endl ;
}

Now there’s a clean-looking block of code. Notice that the dbInitEH(), dbOpenEH(), dbGetDataEH(), and dbCloseEH() function calls are encased within a try block. No checks are made for success or failure for each function call—no need to clutter the code with if-else blocks. The previous block of code constitutes 14 lines of code; this section of code occupies 9 lines of code. Any errors caught in any of the function calls are caught by the associated catch clause.

This is the real intent of exception handling: to separate the recognition and handling of a program anomaly. Let’s take a second look at the previous section of code and discuss the try block and catch clause.

A try block is introduced with the try keyword followed by the block of code to be executed. The try block can be a single statement or a series of statements encased within a left and right brace. It is recommended that you always use the left and right brace as a visual aid and for future maintenance efforts.

All statements within a try block are executed unless one of the statements throws an exception. If any exception is thrown, control is transferred to the catch clause. If a catch clause cannot be found to handle the exception within the current scope, the exception handling mechanism searches up the call chain, attempting to locate a catch clause that can handle the exception. If control must leave the current scope, say to a function block, the stack is unwound and any objects created are properly destroyed. Control is then returned to the calling block so the exception can be handled. Note that any objects created on the free store will not be destroyed.

If no exception handler is found and control has reached the main function, the terminate() function, found within the standard library, is invoked. The default action of the terminate() function is, of course, to terminate the program.

A try block is the same as any other C++ block. You can declare variables, call other functions, execute loop statements, and so on and so forth. Remember that any variables declared will not be accessible outside the try block. Although not an absolute requirement, you should follow a try block with one or more catch clauses that can handle any exceptions that might be thrown.

Let’s take a closer look at the catch clause:

catch( int v )

A catch clause consists of the keyword catch, followed by an argument of some type. The previous catch clause will handle an exception of type int that is thrown within the preceding try block. The argument to a catch clause can be a native type such as int or char*, or it can be a user-defined type.

You can specify one or more catch clauses following a try block. There is a special-case catch clause, known as the catch-all clause. It looks like this:

catch( ... )


Previous Table of Contents Next


Products |  Contact Us |  About Us |  Privacy  |  Ad Info  |  Home

Use of this site is subject to certain Terms & Conditions, Copyright © 1996-1999 EarthWeb Inc.
All rights reserved. Reproduction whole or in part in any form or medium without express written permision of EarthWeb is prohibited.