C++ 초급 - 10. 예외 처리 (2 - throw 키워드 (예외 발생시키기))

2025. 2. 22. 17:19프로그래밍 언어/C++

📌 10.2 throw 키워드 (예외 발생시키기)

C++에서 throw 키워드는 프로그램 실행 중 특정 조건에서 예외를 발생시키는 역할을 한다.
이를 활용하면 예외적인 상황을 감지하고, 해당 오류를 적절하게 처리할 수 있도록 강제할 수 있다.


📌 1. throw 키워드의 기본 개념 (throw 예외객체)

🔹 (1) throw란?

  • throw를 사용하면 예외 객체를 생성하여 예외를 발생시킬 수 있음.
  • throw가 실행되면 즉시 try-catch 블록으로 이동하여 예외를 처리해야 함.
  • throw된 예외가 catch에서 처리되지 않으면 프로그램이 비정상적으로 종료됨.

💡 기본 문법

throw 예외객체;

💡 예제: 기본 throw 사용법

#include <iostream>

int main() {
    try {
        std::cout << "예외 발생 전" << std::endl;
        throw 42;  // 예외 발생
        std::cout << "이 코드는 실행되지 않음" << std::endl;
    }
    catch (int e) {
        std::cout << "예외 발생! 값: " << e << std::endl;
    }

    std::cout << "프로그램 정상 종료" << std::endl;
    return 0;
}

🔹 출력 결과

예외 발생 전
예외 발생! 값: 42
프로그램 정상 종료

💡 설명

  • throw 42;가 실행되면 catch (int e) 블록으로 이동하여 예외를 처리.
  • 예외가 처리되지 않았다면 프로그램이 비정상 종료됨.

📌 2. throw를 활용한 예외 강제 발생

🔹 (1) 조건에 따라 throw를 활용하여 강제 예외 발생 가능

💡 예제: 0으로 나누는 경우 예외 발생

#include <iostream>

double divide(double a, double b) {
    if (b == 0) throw "0으로 나눌 수 없습니다!";  // 예외 발생
    return a / b;
}

int main() {
    try {
        std::cout << "결과: " << divide(10, 0) << std::endl;
    }
    catch (const char* e) {
        std::cout << "예외 처리: " << e << std::endl;
    }

    return 0;
}

🔹 출력 결과

예외 처리: 0으로 나눌 수 없습니다!

💡 설명

  • b == 0인 경우 "0으로 나눌 수 없습니다!"를 throw하여 예외 발생.
  • catch (const char* e)에서 예외를 받아 처리.

📌 3. 사용자 정의 예외 클래스 생성 방법

🔹 (1) std::exception을 상속하여 사용자 정의 예외 클래스 생성

  • C++ 표준 예외 클래스(std::exception)를 상속하면 예외 정보를 더 구체적으로 제공 가능.
  • what() 함수를 오버라이딩하여 사용자 정의 예외 메시지 출력.

💡 예제: 사용자 정의 예외 클래스

#include <iostream>
#include <exception>

// 사용자 정의 예외 클래스
class DivideByZeroException : public std::exception {
public:
    const char* what() const noexcept override {
        return "예외: 0으로 나눌 수 없습니다!";
    }
};

// 예외를 발생시키는 함수
double safeDivide(double a, double b) {
    if (b == 0) throw DivideByZeroException();  // 사용자 정의 예외 발생
    return a / b;
}

int main() {
    try {
        std::cout << "결과: " << safeDivide(10, 0) << std::endl;
    }
    catch (const DivideByZeroException& e) {
        std::cout << e.what() << std::endl;  // 예외 메시지 출력
    }

    return 0;
}

🔹 출력 결과

예외: 0으로 나눌 수 없습니다!

💡 설명

  • DivideByZeroException 클래스는 std::exception을 상속받아 사용자 정의 예외를 제공.
  • what() 함수를 오버라이딩하여 예외 발생 시 메시지를 출력할 수 있도록 구현.

📌 4. 함수에서 예외를 던지고 (throw), try-catch로 처리하는 방법

🔹 (1) 예외를 던지는 함수 (throw)

  • 함수 내부에서 throw로 예외를 던지고, 호출하는 곳에서 try-catch로 예외를 처리.

💡 예제: 함수에서 예외 던지기

#include <iostream>

void checkNumber(int num) {
    if (num < 0) throw std::runtime_error("음수 입력 불가!");  // 예외 발생
    std::cout << "입력된 숫자: " << num << std::endl;
}

int main() {
    try {
        checkNumber(-5);  // 음수 입력 시 예외 발생
    }
    catch (const std::runtime_error& e) {
        std::cout << "예외 처리: " << e.what() << std::endl;
    }

    return 0;
}

🔹 출력 결과

예외 처리: 음수 입력 불가!

💡 설명

  • checkNumber(-5); 실행 시 throw std::runtime_error("음수 입력 불가!"); 발생.
  • catch (const std::runtime_error& e)에서 예외를 처리하여 메시지 출력.

📌 5. throw;를 사용하여 예외를 다시 던지는 방법 (rethrowing)

🔹 (1) throw;를 사용하여 예외를 다시 던지기

  • 예외를 처리한 후 다시 던질 수 있음 (rethrowing).
  • 예외를 중간에서 수정하지 않고 최상위 catch 블록에서 최종 처리할 때 사용.

💡 예제: 예외를 다시 던지는 rethrowing

#include <iostream>
#include <exception>

void firstFunction() {
    try {
        throw std::runtime_error("첫 번째 함수에서 예외 발생!");
    }
    catch (...) {
        std::cout << "firstFunction에서 예외를 다시 던짐!" << std::endl;
        throw;  // 예외를 다시 던짐
    }
}

int main() {
    try {
        firstFunction();
    }
    catch (const std::runtime_error& e) {
        std::cout << "main에서 최종 예외 처리: " << e.what() << std::endl;
    }

    return 0;
}

🔹 출력 결과

firstFunction에서 예외를 다시 던짐!
main에서 최종 예외 처리: 첫 번째 함수에서 예외 발생!

💡 설명

  • firstFunction()에서 catch 블록에서 예외를 잡은 후 throw;로 다시 던짐.
  • main()에서 최종적으로 예외를 처리함.

📌 6. 정리

개념  설명
throw 키워드 예외를 발생시키는 역할 (throw 예외객체;)
예외 강제 발생 특정 조건에서 throw를 활용하여 오류를 강제로 발생
사용자 정의 예외 클래스 std::exception을 상속하여 예외 클래스를 정의하고 what()을 오버라이딩
함수에서 throw 활용 함수 내부에서 예외를 던지고 호출하는 곳에서 try-catch로 처리
예외 다시 던지기 (throw;) 예외를 잡은 후 다시 던져 최상위 catch 블록에서 최종 처리