throw
The throw
keyword in C++ is a fundamental part of exception handling. It is used to generate exceptions when exceptional circumstances occur during program execution. Understanding how to use throw
effectively is crucial for writing robust and error-tolerant C++ programs. Let's explore various examples of using throw
in different contexts.
#include <iostream>
#include <stdexcept>
double divide(double numerator, double denominator) {
if (denominator == 0) {
throw std::runtime_error("Division by zero!");
}
return numerator / denominator;
}
int main() {
try {
std::cout << "Result: " << divide(10, 2) << std::endl;
std::cout << "Result: " << divide(5, 0) << std::endl;
} catch (const std::exception& e) {
std::cerr << "Caught exception: " << e.what() << std::endl;
}
return 0;
}
This example demonstrates the basic usage of throw
:
divide
function that checks for division by zero.std::runtime_error
exception.main
function, we use a try-catch block to handle potential exceptions.#include <iostream>
#include <string>
class NetworkError : public std::exception {
private:
std::string message;
public:
NetworkError(const std::string& msg) : message(msg) {}
const char* what() const noexcept override {
return message.c_str();
}
};
void connectToServer(const std::string& server) {
if (server.empty()) {
throw NetworkError("Empty server address");
}
if (server == "localhost") {
throw NetworkError("Cannot connect to localhost");
}
std::cout << "Connected to " << server << std::endl;
}
int main() {
try {
connectToServer("example.com");
connectToServer("localhost");
} catch (const NetworkError& e) {
std::cerr << "Network error: " << e.what() << std::endl;
}
return 0;
}
This example showcases throwing custom exceptions:
NetworkError
class derived from std::exception
.connectToServer
function throws NetworkError
exceptions for specific conditions.main
, we attempt to connect to different servers within a try block.NetworkError
exceptions.#include <iostream>
#include <stdexcept>
void processData(int data) {
try {
if (data < 0) {
throw std::out_of_range("Data must be non-negative");
}
std::cout << "Processing data: " << data << std::endl;
} catch (const std::exception& e) {
std::cerr << "Error in processData: " << e.what() << std::endl;
throw; // Rethrow the caught exception
}
}
int main() {
try {
processData(5);
processData(-1);
} catch (const std::exception& e) {
std::cerr << "Caught in main: " << e.what() << std::endl;
}
return 0;
}
This example demonstrates rethrowing exceptions:
processData
function throws an exception for negative input.std::exception
, logs an error, and then rethrows the exception using throw;
.main
, we call processData
twice, once with valid data and once with invalid data.processData
is caught in main
.#include <iostream>
#include <stdexcept>
class Resource {
public:
Resource(int id) {
if (id < 0) {
throw std::invalid_argument("Invalid resource ID");
}
std::cout << "Resource " << id << " acquired" << std::endl;
}
~Resource() {
std::cout << "Resource released" << std::endl;
}
};
int main() {
try {
Resource r1(1); // Valid resource
Resource r2(-1); // This will throw
} catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
}
return 0;
}
This example shows throwing exceptions in constructors:
Resource
class constructor throws an exception for invalid IDs.main
, we create two Resource
objects, one valid and one invalid.The throw
keyword in C++ is a powerful tool for exception handling:
std::exception
or its derived classes.throw;
without an argument to propagate them up the call stack.throw
judiciously and handle exceptions appropriately to create robust and reliable C++ programs.Remember that while exceptions are useful for handling error conditions, they should not be used for normal control flow. Overuse of exceptions can make code harder to understand and maintain. Always consider the performance implications and the exception safety guarantees of your code when using throw
.