← Back to C++ Course | Chapter 12: Exception Handling | Lesson 5 of 5

C++ Exception Hierarchy

Overview of Standard Exceptions

C++'s standard exceptions form a hierarchy rooted at std::exception, which branches into two broad categories: std::runtime_error for problems caused by unpredictable external factors, and std::logic_error for bugs that a careful programmer could have prevented ahead of time.

Example: Overview of Standard Exceptions

cpp
#include <iostream>
#include <stdexcept>

int main() {
	try {
		throw std::runtime_error("Runtime issue");
	} catch (std::exception &e) {
		std::cout << e.what() << std::endl;
	}
	return 0;
}

Runtime Errors (runtime_error)

A runtime_error represents a failure that logic checks alone can't reliably predict in advance — things like a network timeout, a hardware fault, or a full disk, which depend on conditions outside the program's own control.

Example: Runtime Errors (runtime_error)

cpp
#include <iostream>
#include <stdexcept>

int main() {
	try {
		throw std::runtime_error("Network timeout");
	} catch (std::runtime_error &e) {
		std::cout << e.what() << std::endl;
	}
	return 0;
}

Logic Errors (logic_error)

A logic_error, by contrast, represents a mistake that was theoretically avoidable through correct code — passing an invalid argument, or trying to access a container element that's out of range, are both classic examples of preventable logic errors.

Example: Logic Errors (logic_error)

cpp
#include <iostream>
#include <stdexcept>

int main() {
	try {
		throw std::invalid_argument("Invalid argument passed");
	} catch (std::logic_error &e) {
		std::cout << e.what() << std::endl;
	}
	return 0;
}

Catching by Base Reference

You should always catch exceptions by const reference rather than by value, because catching by reference preserves the object's real polymorphic type and avoids object slicing, which would otherwise cut a derived exception down to just its base class portion.

Example: Catching by Base Reference

cpp
#include <iostream>
#include <stdexcept>

int main() {
	try {
		throw std::out_of_range("Index out of range");
	} catch (const std::exception &e) {
		std::cout << e.what() << std::endl;
	}
	return 0;
}

Bad Allocations (bad_alloc)

std::bad_alloc is thrown directly by the standard library's memory allocator — most commonly triggered by the new operator — whenever the system genuinely runs out of free heap memory and an allocation request simply cannot be satisfied.

Example: Bad Allocations (bad_alloc)

cpp
#include <iostream>
#include <new>

int main() {
	try {
		throw std::bad_alloc();
	} catch (std::bad_alloc &e) {
		std::cout << e.what() << std::endl;
	}
	return 0;
}
🔒

Chapter Quiz — Complete all 5 topics to unlock

0/5 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.