C++ Tutorial
Class and Object
Reference
Inheritance and Derivation
Polymorphism and Virtual Functions
Operator Overloading
Template
Exception
Object Oriented Advanced
Input/Output Stream
File Operations
In this tutorial, we'll discuss the different types of C++ exceptions and multi-level catch matching. C++ provides exception handling mechanisms that can be utilized to manage errors and unexpected behaviors during program execution.
C++ exceptions can be classified into the following categories:
a) Standard exceptions: C++ has a set of predefined exceptions derived from the std::exception
class, such as std::logic_error
, std::runtime_error
, and their respective subclasses.
b) User-defined exceptions: Developers can create their own exception classes by inheriting from the std::exception
class or its subclasses, and then add custom error messages or additional attributes as needed.
Here's a simple example of a user-defined exception class:
#include <stdexcept> #include <string> class CustomException : public std::runtime_error { public: CustomException(const std::string &message) : std::runtime_error(message) {} };
C++ allows multiple catch blocks to handle exceptions in a hierarchical manner. Catch blocks are matched based on the type of exception thrown. This is particularly useful when there are base and derived classes, allowing you to catch both general and specific exceptions.
Here's an example of multi-level catch matching:
#include <iostream> #include <stdexcept> #include <string> class CustomException : public std::runtime_error { public: CustomException(const std::string &message) : std::runtime_error(message) {} }; void func() { // Throw a CustomException throw CustomException("This is a custom exception"); } int main() { try { func(); } catch (const CustomException &e) { std::cerr << "Caught CustomException: " << e.what() << std::endl; } catch (const std::runtime_error &e) { std::cerr << "Caught std::runtime_error: " << e.what() << std::endl; } catch (const std::exception &e) { std::cerr << "Caught std::exception: " << e.what() << std::endl; } catch (...) { std::cerr << "Caught an unknown exception" << std::endl; } return 0; }
In this example, if the CustomException
is thrown, the first catch block will handle it. If a more general std::runtime_error
or std::exception
is thrown, the second or third catch blocks will handle them, respectively. The last catch block (catch-all) is used to handle any other unknown exceptions.
It's essential to remember that catch blocks should be ordered from most specific to most general, to ensure proper handling of exceptions.
Multi-level catch blocks in C++:
#include <iostream> #include <stdexcept> int main() { try { // Code that may throw exceptions throw std::runtime_error("An error occurred"); } catch (const std::exception& e) { std::cerr << "Caught exception: " << e.what() << std::endl; } catch (...) { std::cerr << "Unknown exception caught" << std::endl; } return 0; }
Exception hierarchy in C++:
#include <iostream> #include <stdexcept> void processFile() { // Code that may throw file-related exceptions throw std::ios_base::failure("File operation failed"); } int main() { try { processFile(); } catch (const std::exception& e) { std::cerr << "Caught exception: " << e.what() << std::endl; } return 0; }
Matching multiple exception types in C++ catch blocks:
#include <iostream> #include <stdexcept> int main() { try { // Code that may throw exceptions throw std::logic_error("Logic error occurred"); } catch (const std::exception& e) { std::cerr << "Caught exception: " << e.what() << std::endl; } return 0; }
Custom exception classes in C++:
#include <iostream> #include <stdexcept> class CustomException : public std::exception { public: const char* what() const noexcept override { return "Custom exception occurred"; } }; int main() { try { // Code that may throw custom exceptions throw CustomException(); } catch (const std::exception& e) { std::cerr << "Caught exception: " << e.what() << std::endl; } return 0; }
Nested catch blocks in C++:
#include <iostream> #include <stdexcept> int main() { try { try { // Code that may throw exceptions throw std::runtime_error("Inner exception"); } catch (const std::exception& inner) { std::cerr << "Inner exception: " << inner.what() << std::endl; throw; // Rethrow the inner exception } } catch (const std::exception& outer) { std::cerr << "Outer exception: " << outer.what() << std::endl; } return 0; }
C++ catching base and derived exceptions:
#include <iostream> #include <stdexcept> class DerivedException : public std::runtime_error { public: explicit DerivedException(const char* msg) : std::runtime_error(msg) {} }; int main() { try { // Code that may throw exceptions throw DerivedException("Derived exception"); } catch (const std::exception& e) { std::cerr << "Caught exception: " << e.what() << std::endl; } return 0; }
Exception types and polymorphism in C++:
#include <iostream> #include <stdexcept> class BaseException : public std::exception { public: const char* what() const noexcept override { return "Base exception occurred"; } }; class DerivedException : public BaseException { public: const char* what() const noexcept override { return "Derived exception occurred"; } }; int main() { try { // Code that may throw exceptions throw DerivedException(); } catch (const BaseException& e) { std::cerr << "Caught exception: " << e.what() << std::endl; } return 0; }
Handling standard exceptions in multi-level catch in C++:
#include <iostream> #include <stdexcept> int main() { try { try { // Code that may throw exceptions throw std::invalid_argument("Invalid argument"); } catch (const std::exception& inner) { std::cerr << "Inner exception: " << inner.what() << std::endl; throw; // Rethrow the inner exception } } catch (const std::exception& outer) { std::cerr << "Outer exception: " << outer.what() << std::endl; } return 0; }
C++ exception specifications and catch clauses:
#include <iostream> #include <stdexcept> void mayThrowException() noexcept(false) { throw std::runtime_error("Exception from mayThrowException"); } int main() { try { mayThrowException(); } catch (const std::exception& e) { std::cerr << "Caught exception: " << e.what() << std::endl; } return 0; }
User-defined exception classes and catch blocks in C++:
#include <iostream> #include <stdexcept> class CustomException : public std::exception { public: const char* what() const noexcept override { return "Custom exception occurred"; } }; int main() { try { // Code that may throw custom exceptions throw CustomException(); } catch (const CustomException& e) { std::cerr << "Caught custom exception: " << e.what() << std::endl; } catch (const std::exception& e) { std::cerr << "Caught exception: " << e.what() << std::endl; } return 0; }
C++ rethrowing exceptions in multi-level catch:
#include <iostream> #include <stdexcept> int main() { try { try { // Code that may throw exceptions throw std::runtime_error("Inner exception"); } catch (const std::exception& inner) { std::cerr << "Inner exception: " << inner.what() << std::endl; throw; // Rethrow the inner exception } } catch (const std::exception& outer) { std::cerr << "Outer exception: " << outer.what() << std::endl; } return 0; }
C++ exception types and error reporting:
#include <iostream> #include <stdexcept> int main() { try { // Code that may throw exceptions throw std::runtime_error("An error occurred"); } catch (const std::exception& e) { std::cerr << "Caught exception: " << e.what() << std::endl; } return 0; }
Examples of multi-level catch matching in C++:
#include <iostream> #include <stdexcept> int main() { try { try { // Code that may throw exceptions throw std::logic_error("Inner logic error"); } catch (const std::exception& inner) { std::cerr << "Inner exception: " << inner.what() << std::endl; throw; // Rethrow the inner exception } } catch (const std::exception& outer) { std::cerr << "Outer exception: " << outer.what() << std::endl; } return 0; }