Catch

(Programming::C++ term)

See Also: try, throw, exception

Note: Please read try before reading this!

In the C++ programming language, the catch keyword can be used to encase a code block to handle various exceptions thrown by a try block. If you are not already familiar with the concepts of a try block, I encourage you to refer to that node first before continuing here. With that settled, let us evaluate the catch block in better detail:

Once a try block throws an exception, the program's execution unwinds, or "back-steps", through the code until it finds an appropriate catch block to handle that exception. If no catch statement/block is provided, the program defaults to whatever your compiler uses as its primary exception handler. More often than not, compilers allow the operating system to deal with the exception. This can result in (multiple) errors and other dangerous side effects (i.e. memory leaks).

Multiple catch blocks can be supplied for a single try block. This means that you are allowed to make multple catch blocks to handle multiple exceptions that may be thrown from one try block. A simple example of this is demonstrated using a string input system. This system checks for multiple conditions in which to throw an exception:


    #include <iostream>
    #include <string>

    using std::cout;
    using std::cin;
    using std::string;

    // Empty class to throw if string is empty
    class XNullString{ };

    // Emtpy class to throw if string is too long ( > 12 char's)
    class XStringTooLong{ };


    int main(int argc, char **argv){
        // We will use this object for our input
        string strInput;

        try {
            // Prompt the user for a string
            cout << "\nPlease input a word that is <= 12 characters long\n";
            cout << "->";
            cin >> strInput;

            // Test for empty string (note: most compilers won't accept a null string anyway)
            if ( strInput.empty() )
                // String is empty, return exception
                throw ( XNullString() );

            // Test for string length
            if ( strInput.size() > 12)
                // String is too long, throw exception
                throw ( XStringTooLong() );
            }

        // Catch the empty string exception
        catch ( XNullString ) {
            cout << "You didn't type anything in!\n";
            // Exit with error status ( return(1) )
            return(1);
            }

        // Catch the string length exception        
        catch ( XStringTooLong ) {
            cout << "The string is too long!\n";
            // Exit with error status ( return(1) )
            return(1);
            }

        // Nothing was thrown! Good!        
        cout << "You typed in: " << strInput << std::endl;
        // Return with successful status ( return(0) )    
        return(0);
        }


You are allowed to create a "catch everything" catch block. Inside of the parenthesis, instead of specifying an object, class, or other exception item, you can supply three ellipses (...). To demonstrate this technique, let's use the same code from before, but create only a single catch block:


    #include <iostream>
    #include <string>

    using std::cout;
    using std::cin;
    using std::string;

    // Empty class to throw if string is empty
    class XNullString{ };

    // Emtpy class to throw is string is too long ( > 12 char's)
    class XStringTooLong{ };


    int main(int argc, char **argv){
        // We will use this object for our input
        string strInput;

        try {
            // Prompt the user for a string
            cout << "\nPlease input a word that is <= 12 characters long\n";
            cout << "->";
            cin >> strInput;

            // Test for empty string (note: most compilers won't accept a null string anyway)
            if ( strInput.empty() )
                // String is empty, return exception
                throw ( XNullString() );

            // Test for string length
            if ( strInput.size() > 12)
                // String is too long, throw exception
                throw ( XStringTooLong() );
            }

        // Catch EVERYTHING
        catch (...) {
            cout << "Error Caught!\n";
            // Return with error status ( return(1) )
            return(1);
            }

        // Nothing was thrown! Good!        
        cout << "You typed in: " << strInput << std::endl;
        // Return with successful status ( return(0) )    
        return(0);
        }


If the try block in this program throws an exception, regardless of which exception it is, the single catch block will be executed. This is generally NOT a good habit to become accustomed to. If you know beforehand what possible exceptions may be thrown in your program, you should take the extra time to create the appropriate catch blocks to facilitate them. The "catch everything" block can always be used after all 'specific' catch blocks have been written, allowing the program to catch those specific exceptions...and if any unknown (or unexpected) exception occurs, catch it with the "catch everything" block.

Do NOT attempt to do anything in a catch block that resulted in that exception being thrown (ex. If you caught a failed allocation variable, do not try to allocate anything). This is emphasized in many C++ programming books, but often over-looked!.

Just as you can nest try blocks (within other try blocks), you can nest catch blocks within other try/catch blocks.


Please view the node throw for more detailed information on what you can throw!