이 글은 개인의 학습을 목적으로 정리한 글입니다. 이점 참고하고 읽어주세요 ;)
프로그램을 작성하고 실행시킬 때, 우리는 설계한 프로그램에 적합하지 않은 입력값으로 인해 오류가 발생하는 걸 방지해야 합니다. 이렇게 오류가 발생하는 걸 사전에 처리하는 방법 중에 하나가 예외처리라고 합니다. 이번 포스팅에서는 예외처리의 기본에 대해 다뤄보겠습니다.
double divide(int x, int y, bool& success)
{
if (y == 0)
{
success = false;
return 0.0;
}
success = true;
return static_cast<double>(x) / y;
}
여기 나눗셈 연산을 해주는 divide 함수를 만들었습니다.
나눗셈 결과를 double 자료형으로 출력해주고,
매개변수로 분자 x, 분모 y, 그리고 나눗셈 연산의 성공 여부를 알려줄 success를 bool 자료형의 레퍼런스로 받습니다.
만약 분모가 0이라면 나눗셈을 할 수 없기 때문에, y가 0일 때는 success에 false값을 주고 0.0을 리턴합니다.
그리고 y가 0이 아니라면 success에 true 값을 주고, 나눗셈을 한 결과를 리턴합니다.
bool success;
double result = divide(5, 3, success);
if (!success)
std::cerr << "An error occured" << endl;
else
std::cout << "Result is " << result << endl;
divide 함수를 main함수에서 사용하는 방법은 위의 코드 블록과 같습니다.
포인트는 success 변수를 매개변수로 주고,
만약 divide 함수에서 나눗셈이 실행되지 못해 success가 false를 받았다면 에러가 발생했다는 문구를 출력하고
그렇지 않으면 정상적으로 나눗셈의 결과 값을 출력합니다.
이게 C++에서 전통적으로 오류를 잡는 방법이라고 하는데, 퍼포먼스를 향상하기 위한 것이 그 이유 중 하나라고 합니다.
지금부터 설명할 예외처리 역시 오류를 잡는 방법 중 하나입니다. 예외처리가 위에서 다룬 예제와 같은 방식의 오류 처리를 완전히 대체할 수 있는 건 아닙니다. 프로그램의 특성에 따라 예외처리를 사용할지, 아니면 다른 방식을 사용할지 결정해야 합니다.
예외처리 문법은 위의 예제와 같은 오류처리 방식보다 시간이 더 걸린다고 합니다. 때문에 인공지능에서 빅데이터를 훈련시키는 등의 퍼포먼스가 중요한 프로그램보다는 서버 운영과 같이 사소한 오류가 발생해도 시스템을 꼭 유지해야 하는 프로그램에 더 적합하다고 할 수 있습니다.
#include <iostream>
#include <string>
int main()
{
double x;
cin >> x;
try
{
if( x < 0.0 ) throw std::string "Negative input";
cout << std::sqrt(x) << endl;
}
catch (std::string error_message)
{
cout << error_message << endl;
}
return 0;
}
예외처리의 기본 틀은 위의 코드 블록과 같습니다. 주의 깊게 봐야 할 점은 try, throw, catch입니다.
try 구문 안에는 프로그래머가 지정한 조건일 경우에서 에러 메시지를 던지는throw 변수를 작성합니다.
throw 옆에 catch에게 전달할 변수를 입력해야 하는데, 자료형과 그 값을 정확하게 전달해야 합니다.
여기서는 x가 0보다 작을 때 string 자료형의 "Negative input"이라는 문장을 catch에게 전달하고, 그렇지 않을 경우 x의 제곱근을 출력합니다.
catch 선언 옆에는 throw로 전달받을 매개변수를 입력해야 합니다. 위 예제에서는 string 자료형의 데이터를 받을 것이기 때문에 std::string error_message를 입력했습니다. error_message는 매개변수의 이름으로 catch 구문 내에서 사용됩니다.
catch에서 받는 매개변수는 그 자료형을 엄격하게 따집니다. 때문에 만약 try구문에서 string 자료형의 문장을 throw하지 않고 int, float과 같은 다른 자료형을 전달하게 되면 catch가 이를 받지 못하고 런타임 에러가 발생합니다.
코드를 통해 설명하면,
try
{
// throw std::string("My error message!");
// throw -1;
// throw 1.5;
// throw 'My error message!';
}
catch (int x)
{
cout << "Catch integer" << x << endl;
}
catch (double x)
{
cout << "Catch double " << x << endl;
}
catch (const char* error_message)
{
cout << "Char* " << error_message << endl;
}
catch (std::string error_message)
{
cout << error_message << endl;
}
try 구문에서 주석 처리한 코드 중 어떤 값을 throw 하느냐에 따라 밑에 있는 다양한 catch 구문 중 호출될 catch 구문이 결정됩니다.
'Information Technology > C++' 카테고리의 다른 글
[C++] 예외 클래스와 상속 (0) | 2019.11.25 |
---|---|
[C++] 예외처리와 스택 되감기 (0) | 2019.11.25 |
[C++] 템플릿의 부분적 특수화 (0) | 2019.11.21 |
[C++] 클래스 템플릿 특수화 (0) | 2019.11.20 |
[C++] 함수 템플릿 특수화 (0) | 2019.11.20 |