C++에서 예외 처리(Exception Handling)란 프로그램 실행 중에 발생하는 런타임 오류를 처리하는 메커니즘을 말합니다. 예외(Exception)는 프로그램이 실행되는 도중에 발생(throw)되는 이벤트로, C++의 모든 표준 예외는 std::exception 클래스를 기반으로 파생됩니다. 만약 예외를 적절히 처리하지 않으면, 프로그램은 예외 메시지를 출력한 뒤 비정상적으로 종료됩니다.
C++ 표준에서는 <exception> 헤더를 통해 다양한 예외 클래스를 정의하고 있으며, 이를 프로그램 안에서 자유롭게 활용할 수 있습니다. 부모-자식 클래스로 이루어진 계층 구조는 아래와 같습니다.

C++의 주요 표준 예외 클래스
| 예외 클래스 | 설명 |
|---|---|
| std::exception | 모든 표준 C++ 예외 클래스의 부모(기반) 클래스입니다. |
| std::bad_cast | dynamic_cast가 실패할 때 던져지는 예외입니다. |
| std::bad_exception | 프로그램에서 예상치 못한 예외를 처리하는 데 사용됩니다. |
| std::bad_alloc | new 연산자가 메모리 할당에 실패했을 때 일반적으로 던져지는 예외입니다. |
| std::logic_error | 코드를 검토함으로써 사전에 감지할 수 있는 논리적 오류입니다. |
| std::runtime_error | 코드 검토만으로는 감지할 수 없고 실행 중에 발생하는 오류입니다. |
| std::bad_typeid | typeid 연산자가 실패할 때 던져지는 예외입니다. |
예외 처리의 핵심 키워드 3가지
C++의 예외 처리에는 세 가지 핵심 키워드가 사용됩니다: try, catch, throw.
- throw: 문제가 발생했음을 알리고 예외를 던질 때 사용합니다.
- try: 예외가 발생할 가능성이 있는 코드를 감싸는 블록입니다.
- catch: try 블록에서 던져진 예외를 받아 처리하는 블록입니다.
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;
}
}
위 예제에서 주목할 점은 Sample2 객체의 생성자에서 예외가 던져졌기 때문에 Sample2의 소멸자는 호출되지 않지만, 이미 생성이 완료된 Sample1 객체의 소멸자는 정상적으로 호출된다는 것입니다. 이처럼 C++은 스택 풀기(stack unwinding) 과정을 통해 이미 생성된 지역 객체들을 자동으로 정리해 줍니다.
실행 결과
Construct an Object of sample1 Construct an Object of sample2 Destruct an Object of sample1 Caught 7
사용자 정의 예외(User Defined Exception)
C++에서는 std::exception 클래스를 상속받고 what() 함수를 재정의(오버라이딩)하여 자신만의 예외 클래스를 정의할 수 있습니다.
예제 코드
#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 메서드로, 모든 자식 예외 클래스들이 이를 재정의하여 사용합니다. 이 메서드는 예외가 발생한 원인을 설명하는 문자열을 반환하며, 어떤 문제로 인해 예외가 발생했는지 파악하는 데 유용하게 활용됩니다.