C++ 예외 처리
예외는 프로그램 실행 중에 발생하는 문제입니다. C++ 예외는 0으로 나누려는 시도와 같이 프로그램이 실행되는 동안 발생하는 특별한 상황입니다.
예외는 프로그램 제어를 전송하는 방법을 제공합니다. C++ 예외 처리에는 try, catch 및 throw라는 세 가지 키워드가 포함됩니다.
throw: 문제가 발생하면 프로그램에서 예외가 발생합니다. 이는 throw 키워드를 사용하여 수행됩니다.
catch: 문제를 처리하려는 지점에서 예외 처리기를 사용하여 예외를 포착합니다. catch 키워드는 예외를 잡는 데 사용됩니다.
try: try 블록의 코드는 활성화될 특정 예외를 식별합니다. 일반적으로 다음에는 하나 이상의 catch 블록이 옵니다.
블록에서 예외가 발생하는 경우 예외를 포착하는 방법은 try 및 catch 키워드를 사용합니다. 예외를 발생시킬 수 있는 코드는 try 블록에 배치됩니다. try 블록에 있는 코드를 보호 코드라고 합니다. try/catch 문을 사용하는 구문은 다음과 같습니다.
try { // 保护代码 }catch( ExceptionName e1 ) { // catch 块 }catch( ExceptionName e2 ) { // catch 块 }catch( ExceptionName eN ) { // catch 块 }
try 블록이 다양한 상황에서 다양한 예외를 발생시키는 경우 여러 catch 문을 나열하여 다양한 유형의 예외를 포착할 수 있습니다.
예외 발생
throw 문을 사용하여 코드 블록의 어느 위치에서나 예외를 발생시킬 수 있습니다. throw 문의 피연산자는 모든 표현식이 될 수 있으며 표현식 결과 유형에 따라 발생하는 예외 유형이 결정됩니다.
다음은 0으로 나누려고 할 때 발생하는 예외의 예입니다.
double division(int a, int b) { if( b == 0 ) { throw "Division by zero condition!"; } return (a/b); }
catch 예외
catch 블록은 try 블록을 따라가며 예외를 포착합니다. catch 키워드 뒤의 괄호 안에 있는 예외 선언에 따라 결정되는 catch하려는 예외 유형을 지정할 수 있습니다.
try { // 保护代码 }catch( ExceptionName e ) { // 处理 ExceptionName 异常的代码 }
위 코드는 ExceptionName 유형의 예외를 포착합니다. catch 블록이 try 블록에서 발생한 모든 유형의 예외를 처리할 수 있도록 하려면 다음과 같이 예외 선언의 대괄호 안에 줄임표를 사용해야 합니다.
try { // 保护代码 }catch(...) { // 能处理任何异常的代码 }
다음은 나누기를 던지는 예입니다. 제로 예외로 처리하고 catch 블록에서 예외를 포착합니다.
#include <iostream> using namespace std; double division(int a, int b) { if( b == 0 ) { throw "Division by zero condition!"; } return (a/b); } int main () { int x = 50; int y = 0; double z = 0; try { z = division(x, y); cout << z << endl; }catch (const char* msg) { cerr << msg << endl; } return 0; }
const char* 유형의 예외를 발생시키므로 예외를 잡을 때 catch 블록에서 const char*를 사용해야 합니다. 위 코드를 컴파일하고 실행하면 다음과 같은 결과가 생성됩니다.
Division by zero condition!
C++ 표준 예외
C++는 <예외>에 정의된 일련의 표준 예외를 제공하며, 이를 프로그램에서 사용할 수 있습니다. 이 기준에. 이는 다음과 같이 상위-하위 클래스 계층 구조로 구성됩니다.
다음 표는 위 계층 구조에서 발생하는 각 예외에 대한 설명입니다.
Exception | Description |
---|---|
std::Exception | 이 예외는 모든 표준 C++ 예외의 상위 클래스입니다. |
std::bad_alloc | 이 예외는 new에 의해 발생할 수 있습니다. |
std::bad_cast | 이 예외는 dynamic_cast에 의해 발생할 수 있습니다. |
std::bad_Exception | 이는 C++ 프로그램에서 예상치 못한 예외를 처리할 때 매우 유용합니다. |
std::bad_typeid | 이 예외는 typeid에 의해 발생할 수 있습니다. |
std::logic_error | 이론적으로 코드를 읽어 감지할 수 있는 예외입니다. |
std::domain_error | 이 예외는 잘못된 수학 도메인이 사용될 때 발생합니다. |
std::invalid_argument | 이 예외는 잘못된 매개변수가 사용되는 경우 발생합니다. |
std::length_error | 이 예외는 너무 긴 std::string이 생성될 때 발생합니다. |
std::out_of_range | 이 예외는 std::Vector 및 std::bitset<>::operator[]()와 같은 메서드에 의해 발생할 수 있습니다. |
std::runtime_error | 이론적으로 코드를 읽어도 감지할 수 없는 예외입니다. |
std::overflow_error | 이 예외는 수학적 오버플로가 발생할 때 발생합니다. |
std::range_error | 이 예외는 범위를 벗어난 값을 저장하려고 할 때 발생합니다. |
std::underflow_error | 이 예외는 수학적 언더플로가 발생할 때 발생합니다. |
새 예외 정의
Exception 클래스를 상속하고 오버로드하여 새 예외를 정의할 수 있습니다. 다음 예제에서는 std::Exception 클래스를 사용하여 사용자 고유의 예외를 구현하는 방법을 보여줍니다.
#include <iostream> #include <exception> using namespace std; struct MyException : public exception { const char * what () const throw () { return "C++ Exception"; } }; int main() { try { throw MyException(); } catch(MyException& e) { std::cout << "MyException caught" << std::endl; std::cout << e.what() << std::endl; } catch(std::exception& e) { //其他的错误 } }
이렇게 하면 다음과 같은 결과가 생성됩니다.
MyException caught C++ Exception
여기서 what()은 예외 클래스에서 제공하는 공용 메서드입니다. 모든 하위 예외 클래스에 대해 오버로드되었습니다. 그러면 예외 이유가 반환됩니다.