C++에서 예외 처리(Exception Handling)는 프로그램 실행 중 발생하는 런타임 오류를 감지하고 대응하기 위한 메커니즘입니다. 예외(Exception)란 프로그램이 실행되는 도중에 발생하여 던져지는(throw) 이벤트를 의미하며, C++의 모든 표준 예외는 std::exception 클래스로부터 파생됩니다. 만약 예외를 적절히 처리하지 않으면 프로그램은 예외 메시지를 출력한 뒤 강제로 종료됩니다.
C++ 표준에서는 이러한 예외들을 <exception> 헤더의 클래스 형태로 정의하고 있어, 프로그램 내에서 언제든 활용할 수 있습니다. 부모-자식 관계로 이루어진 예외 클래스 계층 구조는 아래와 같습니다.

C++의 주요 표준 예외 클래스
| 번호 | 예외 클래스 및 설명 |
|---|---|
| 1 | std::exception 모든 표준 C++ 예외 클래스의 부모가 되는 최상위 예외 클래스입니다. |
| 2 | std::bad_castdynamic_cast가 실패했을 때 던져지는 예외입니다. |
| 3 | std::bad_exception 프로그램에서 예상치 못한 예외가 발생했을 때 이를 처리하기 위해 사용되는 예외입니다. |
| 4 | std::bad_allocnew 연산자를 통한 동적 메모리 할당이 실패할 때 일반적으로 던져지는 예외입니다. |
| 5 | std::logic_error 코드를 검토하는 것만으로도 발생 여부를 사전에 파악할 수 있는 논리적 오류에 해당하는 예외입니다. |
| 6 | std::runtime_error 코드 검토만으로는 감지할 수 없고, 실제 실행 과정에서만 확인 가능한 오류에 해당하는 예외입니다. |
| 7 | std::bad_typeidtypeid 연산자가 실패했을 때 던져지는 예외입니다. |
예외 처리의 3대 핵심 키워드
C++의 예외 처리에는 try, catch, throw라는 세 가지 핵심 키워드가 사용됩니다.
try/catch 블록
C++에서는 try/catch 문을 통해 예외를 처리합니다. 예외가 발생할 가능성이 있는 코드는 try 블록 안에 작성하고, 실제로 예외가 발생했을 때 이를 잡아내어 처리하는 역할은 catch 블록이 담당합니다.
예제 코드
#include <iostream>
using namespace std;
class Sample1 {
public:
Sample1() {
cout << "Construct an Object of sample1" << endl;
}
~Sample1() {
cout << "Destruct an Object of sample1" << endl;
}
};
class Sample2 {
public:
Sample2() {
int i=7;
cout << "Construct an Object of sample2" << endl;
throw i;
}
~Sample2() {
cout << "Destruct an Object of sample2" << endl;
}
};
int main() {
try {
Sample1 s1;
Sample2 s2;
} catch(int i) {
cout << "Caught " << i << endl;
}
}
실행 결과
Construct an Object of sample1 Construct an Object of sample2 Destruct an Object of sample1 Caught 7
위 예제에서 Sample2 객체의 생성자가 호출되던 도중 예외가 던져졌습니다. 이때 스택 풀기(Stack Unwinding) 과정이 진행되면서 이미 생성이 완료된 s1 객체의 소멸자가 자동으로 호출되는 것을 확인할 수 있습니다. 반면, 생성이 완료되지 않은 s2의 소멸자는 호출되지 않습니다.
사용자 정의 예외(User Defined Exception)
표준 exception 클래스를 상속받고 필요한 기능을 재정의(오버라이딩)하면, 개발자가 직접 자신만의 예외 클래스를 정의할 수도 있습니다.
예제 코드
#include <iostream>
#include <exception>
using namespace std;
struct DivideByZero : public exception {
const char * what () const throw () {
return "My Exception";
}
};
int main() {
try {
throw DivideByZero();
} catch(DivideByZero& e) {
cout << "Exception caught" << endl;
cout << e.what() << endl;
} catch(exception& e) {
}
}
실행 결과
Exception caught My Exception
what() 메서드란?
what()은 exception 클래스가 제공하는 public 메서드로, 모든 하위 예외 클래스에서 재정의할 수 있습니다. 이 메서드는 예외가 발생한 원인을 설명하는 문자열을 반환하며, 위 예제에서는 DivideByZero 클래스에서 이를 오버라이딩하여 "My Exception"이라는 메시지를 반환하도록 구현했습니다.
참고로 const throw() 같은 동적 예외 명세는 C++11 이후 폐기(deprecated)되었으므로, 현대 C++에서는 noexcept 키워드를 사용하는 것이 권장됩니다.