ScholarQuill logoScholarQuillUniversity Notes
  • Notes
  • Past Papers
  • Blogs
  • Todo
Login
ScholarQuill logoScholarQuillUniversity Notes
Login
NotesPast PapersBlogsTodo
More
SubjectsDiscussionCGPA CalculatorGPA CalculatorStudent PortalCourse Outline
About
About usPrivacy PolicyReportContact
Notes
Past Papers
Blogs
Todo
Analytics
    Current Subject
    🧩
    Object Oriented Programming
    CSI-312
    Progress0 / 16 topics
    Topics
    1. Evolution of Object-Oriented (OO) Programming2. Object-Oriented (OO) Concepts and Principles3. Problem Solving in OO Paradigm4. OO Programme Design Process5. Classes6. Methods7. Objects and Encapsulation8. Constructors and Destructors9. Operator Overloading10. Function Overloading11. Virtual Functions12. Derived Classes13. Inheritance14. Polymorphism15. I/O and File Processing16. Exception Handling
    CSI-312›Exception Handling
    Object Oriented ProgrammingTopic 16 of 16

    Exception Handling

    8 minread
    1,283words
    Intermediatelevel

    Exception Handling in C++

    Exception Handling is a powerful feature in C++ that helps deal with runtime errors in a structured manner. Instead of letting errors disrupt the flow of the program, exceptions allow us to handle errors and recover from them without crashing the program.

    In C++, exception handling is achieved using a combination of three keywords:

    • try: Defines a block of code in which exceptions can occur.
    • throw: Used to throw an exception when an error is encountered.
    • catch: Catches and handles the exception thrown by the throw keyword.

    Basic Syntax of Exception Handling

    The syntax for exception handling in C++ is as follows:

    try {
        // Code that may throw an exception
    }
    catch (exception_type1 ex1) {
        // Handle exception_type1
    }
    catch (exception_type2 ex2) {
        // Handle exception_type2
    }
    catch (...) {
        // Handle any unknown exception
    }
    
    1. try Block: The code that might throw an exception is placed inside the try block.
    2. throw Statement: When a problem occurs in the try block, an exception is thrown using the throw keyword.
    3. catch Block: The catch block handles the exception, and the type of exception is specified to catch different exceptions.

    Example: Basic Exception Handling

    #include <iostream>
    using namespace std;
    
    int divide(int numerator, int denominator) {
        if (denominator == 0) {
            throw "Division by zero is not allowed!";  // Throwing an exception
        }
        return numerator / denominator;
    }
    
    int main() {
        try {
            int result = divide(10, 0);  // Trying to divide by zero
            cout << "Result: " << result << endl;
        }
        catch (const char* msg) {  // Catching the thrown exception
            cout << "Error: " << msg << endl;
        }
    
        return 0;
    }
    

    Explanation:

    • Inside the divide() function, if the denominator is 0, an exception is thrown with the message "Division by zero is not allowed!".
    • In the main() function, the exception is caught by the catch block, and the error message is printed.

    Output:

    Error: Division by zero is not allowed!
    

    Types of Exceptions in C++

    Exceptions in C++ can be of any type. The most common types are:

    1. Predefined Exception Classes: C++ provides a hierarchy of exception classes.

      • std::exception: Base class for all standard exceptions.
      • std::runtime_error: Derived from std::exception, used for errors that can occur during the program’s runtime.
      • std::logic_error: Derived from std::exception, used for errors that occur due to logic problems (like invalid arguments).
    2. Custom Exceptions: You can also define your own exception classes by deriving them from std::exception or any other class.


    Example: Using Standard Exception Classes

    #include <iostream>
    #include <stdexcept>  // For standard exception classes
    using namespace std;
    
    void testException(int num) {
        if (num == 0) {
            throw runtime_error("Runtime error: Number cannot be zero!");
        }
        if (num < 0) {
            throw logic_error("Logic error: Negative number is not allowed!");
        }
        cout << "Number is: " << num << endl;
    }
    
    int main() {
        try {
            testException(0);  // Throws runtime_error
        }
        catch (const runtime_error& e) {
            cout << "Caught exception: " << e.what() << endl;
        }
    
        try {
            testException(-1);  // Throws logic_error
        }
        catch (const logic_error& e) {
            cout << "Caught exception: " << e.what() << endl;
        }
    
        return 0;
    }
    

    Explanation:

    • The function testException() throws a runtime_error if the input is 0, and a logic_error if the input is a negative number.
    • The catch blocks are used to catch and handle the different types of exceptions (runtime_error and logic_error).

    Output:

    Caught exception: Runtime error: Number cannot be zero!
    Caught exception: Logic error: Negative number is not allowed!
    

    Multiple Catch Blocks

    You can have multiple catch blocks to handle different types of exceptions separately. C++ evaluates the catch blocks from top to bottom, and once a match is found, it executes that block and skips the rest.

    #include <iostream>
    #include <stdexcept>
    using namespace std;
    
    void testExceptions(int num) {
        if (num == 0) {
            throw runtime_error("Runtime error: Number cannot be zero!");
        }
        else if (num < 0) {
            throw logic_error("Logic error: Negative number is not allowed!");
        }
        else if (num > 100) {
            throw overflow_error("Overflow error: Number is too large!");
        }
        cout << "Valid number: " << num << endl;
    }
    
    int main() {
        try {
            testExceptions(0);   // Throws runtime_error
        }
        catch (const runtime_error& e) {
            cout << "Caught: " << e.what() << endl;
        }
        
        try {
            testExceptions(-5);  // Throws logic_error
        }
        catch (const logic_error& e) {
            cout << "Caught: " << e.what() << endl;
        }
        
        try {
            testExceptions(150); // Throws overflow_error
        }
        catch (const overflow_error& e) {
            cout << "Caught: " << e.what() << endl;
        }
    
        return 0;
    }
    

    Output:

    Caught: Runtime error: Number cannot be zero!
    Caught: Logic error: Negative number is not allowed!
    Caught: Overflow error: Number is too large!
    

    Catch-All Handler (catch(...))

    The catch(...) block is used to catch any type of exception that doesn't match the specific exception types provided in the preceding catch blocks. It is useful for handling unknown or unexpected exceptions.

    #include <iostream>
    using namespace std;
    
    void testException() {
        throw 42;  // Throwing an integer
    }
    
    int main() {
        try {
            testException();  // Calling function that throws an exception
        }
        catch (int e) {  // Catching integer exceptions
            cout << "Caught an integer exception: " << e << endl;
        }
        catch (...) {  // Catching any other exception
            cout << "Caught an unknown exception!" << endl;
        }
    
        return 0;
    }
    

    Explanation:

    • The throw 42; statement throws an integer exception.
    • The catch(int e) block handles the integer exception.
    • The catch(...) block catches any other exceptions (if the type doesn't match the specified one).

    Output:

    Caught an integer exception: 42
    

    Re-throwing Exceptions

    Sometimes, you may want to catch an exception, process it, and then re-throw it to be handled by another part of the program. This can be done using the throw keyword inside a catch block.

    #include <iostream>
    using namespace std;
    
    void funcA() {
        try {
            throw "Error in funcA";  // Throwing an exception in funcA
        }
        catch (const char* msg) {
            cout << "Caught in funcA: " << msg << endl;
            throw;  // Re-throwing the caught exception
        }
    }
    
    int main() {
        try {
            funcA();  // Call function which throws and re-throws an exception
        }
        catch (const char* msg) {
            cout << "Caught in main: " << msg << endl;
        }
    
        return 0;
    }
    

    Explanation:

    • The exception is thrown in funcA(), caught within funcA(), and then re-thrown to be caught in the main() function.

    Output:

    Caught in funcA: Error in funcA
    Caught in main: Error in funcA
    

    Conclusion

    Exception handling in C++ provides a robust mechanism to deal with errors and exceptions that may occur during runtime. The key elements are:

    1. try block: To define a section of code that might throw exceptions.
    2. throw keyword: Used to throw an exception.
    3. catch block: To handle specific types of exceptions.
    4. Standard exception classes: Predefined exceptions like std::runtime_error, std::logic_error, and std::overflow_error.
    5. Re-throwing exceptions: Allows passing exceptions up the call stack for further handling.

    Exception handling provides a structured and clean way to handle errors, making your programs more resilient and maintainable.

    Previous topic 15
    I/O and File Processing

    Past Papers

    Open this section to load past papers

    Click on Show Past Papers to see past papers.
    On This Page
      Reading Stats
      Est. reading time8 min
      Word count1,283
      Code examples0
      DifficultyIntermediate