Exception handling is a mechanism to handle runtime errors, which may occur due to various reasons like invalid input, hardware failure, or other unexpected issues that can disrupt the normal flow of the program. C++ provides a robust mechanism for dealing with exceptions, which allows programmers to write code that can gracefully handle errors without crashing the program.
In C++, exception handling is done using the try, throw, and catch keywords.
try {
// Code that might throw an exception
} catch (exceptionType1& e) {
// Handle exception of type exceptionType1
} catch (exceptionType2& e) {
// Handle exception of type exceptionType2
} catch (...) {
// Catch any exception (catch-all)
}
try block.throw statement is used to "throw" an exception. The type of the exception can be a built-in type (e.g., int, char) or a user-defined type (e.g., a class).catch block that handles the exception. The catch block is able to handle the specific exception type it is designed for.catch block matches the thrown exception, the catch-all block catch(...) is used to handle any type of exception.Let's look at a basic example of exception handling:
#include <iostream>
using namespace std;
int divide(int a, int b) {
if (b == 0) {
throw "Division by zero error!"; // Throwing an exception
}
return a / b;
}
int main() {
int num1 = 10, num2 = 0;
try {
int result = divide(num1, num2); // Try to divide
cout << "Result: " << result << endl;
} catch (const char* msg) {
cout << "Caught an exception: " << msg << endl; // Catch the exception
}
return 0;
}
Explanation:
divide() function, if b is zero, a string exception is thrown using throw "Division by zero error!".main(), the try block calls the divide() function. If an exception is thrown, the catch block catches it and prints the error message.Caught an exception: Division by zero error!
try block.try block (e.g., due to a zero denominator), control is transferred to the appropriate catch block.catch block executes and handles the exception.catch block is skipped, and the program continues after the try-catch blocks.You can have multiple catch blocks to handle different types of exceptions:
#include <iostream>
using namespace std;
void process(int num) {
if (num == 0) {
throw "Zero is not allowed!"; // Throw string exception
}
if (num < 0) {
throw -1; // Throw integer exception
}
cout << "Processing number: " << num << endl;
}
int main() {
try {
process(0); // Throws string exception
} catch (const char* msg) {
cout << "Caught exception: " << msg << endl;
} catch (int e) {
cout << "Caught exception with code: " << e << endl;
}
return 0;
}
Output:
Caught exception: Zero is not allowed!
If we pass a negative number to process(), it would catch the integer exception.
C++ provides a hierarchy of predefined exception classes in the Standard Library. These are defined under the std namespace and inherit from the base class std::exception.
std::invalid_argument, std::out_of_range.std::overflow_error, std::underflow_error.#include <iostream>
#include <stdexcept>
using namespace std;
void checkNumber(int num) {
if (num < 0) {
throw invalid_argument("Negative numbers are not allowed.");
} else if (num == 0) {
throw runtime_error("Zero is not a valid number.");
}
}
int main() {
try {
checkNumber(-1); // Will throw invalid_argument exception
} catch (const invalid_argument& e) {
cout << "Caught exception: " << e.what() << endl;
} catch (const runtime_error& e) {
cout << "Caught exception: " << e.what() << endl;
}
return 0;
}
Output:
Caught exception: Negative numbers are not allowed.
e.what(): The what() function returns a description of the exception. This is a method defined in the std::exception class, which is inherited by all exceptions.When an exception is thrown, the C++ runtime performs stack unwinding, which involves:
try block.catch block.You can create custom exception classes by inheriting from std::exception and overriding the what() method:
#include <iostream>
#include <stdexcept>
using namespace std;
class MyException : public exception {
public:
const char* what() const noexcept override {
return "This is a custom exception!";
}
};
void triggerException() {
throw MyException(); // Throw custom exception
}
int main() {
try {
triggerException(); // Calls function that throws exception
} catch (const MyException& e) {
cout << "Caught: " << e.what() << endl;
}
return 0;
}
Output:
Caught: This is a custom exception!
catch (const std::exception& e) { ... }
Exception handling in C++ is a powerful mechanism to deal with errors in a controlled way, allowing you to separate error-handling logic from normal program flow. By using try, throw, and catch, you can catch exceptions and prevent program crashes. The C++ Standard Library provides built-in exception types, but you can also create your own custom exceptions. Proper exception handling improves program robustness and makes error handling more manageable.
Open this section to load past papers