An exception is a C++ control-flow mechanism for signaling that a function cannot complete its requested work. It separates the normal path from recovery code and moves the error to a site that may handle it more meaningfully. section 10.1 section 10.1.1
Use exceptions when the called code cannot fulfill its purpose for the caller:
- Detect the failure where it occurs, then throw an exception if that code cannot recover. section 10.1.2
- Catch the exception at a recovery site that understands what action is possible; rethrow or transform it when necessary. section 10.1.6 section 10.1.8
- Prefer exception types and messages over ambiguous return-code values when the failure needs distinct meaning. section 10.1.4 section 10.1.5
- Do not treat exceptions as automatic correctness: an uncaught exception terminates the program, while a careless handler may still fail to recover. section 10.1.6
Replace exit with an exception
Calling exit(-1) after acquiring a database connection prevents the Connection destructor from running and leaks the resource. Throwing instead unwinds the stack, allowing the connection to be released. A practical repair is to throw a specific failure such as TerminatedEmployee and let an outer catch block rethrow or handle it. The same principle applies to constructors: reject invalid input before an object becomes partially initialized. For example, validation can throw std::invalid_argument or std::out_of_range during member initialization. section 5.9 section 10.2
Listing 5.21 Terminating a program with an exception
class Connection {
private:
int conn;
public:
Connection(const std::string& name) : conn(0) {
conn = 1; // assume: database connection resource is allocated
}
~Connection() {
if (conn)
conn = 0; // assume: returns database connection to pool
std::cerr << "Connection destroyed\n";
}
};
struct Employee {
bool isTerminated() { return true; }
double computePay() { return 42.0; }
};
struct TerminatedEmployee {
std::string message;
TerminatedEmployee(const std::string& msg) : message(msg) {}
};
int main() {
try {
Connection c("payroll");
Employee emp;
if (emp.isTerminated())
throw TerminatedEmployee("Employee was terminated");
std::cout << emp.computePay() << '\n';
} catch (...) {
throw; #1
}
return 0;
}
Shows a resource-owning Connection object, a TerminatedEmployee exception, stack unwinding, and an outer rethrow. section 5.9
Throw exceptions by value and catch them by const reference, rather than throwing pointers or catching by value. Also distinguish C++ exceptions from runtime signals: a divide-by-zero signal does not enter a C++ catch block, so preventing the operation and throwing a C++ exception is more reliable. section 10.9 section 12.1
























