반응형
→ 우리에게 익숙한 예외처리는 if문을 이용한 예외처리임.
하지만 if문을 보고 예외처리를 위한 코드인지 프로그램의 흐름을 구성하는 코드인지 쉽게 구분하지 못해서 가독성이 떨어짐.
- C++의 예외처리 메커니즘을 이용하면 가독성을 높일 수가 있다.
- C++은 구조적으로 예외를 처리할 수 있는 메커니즘을 제공한다.
- 가독성과 유지보수성을 높일 수 있을 뿐만 아니라, 예외의 처리를 프로그램의 일반적인 흐름에서 독립시키는 것이 가능하다.
Try
- Try 블록은 예외 발생에 대한 검사의 범위를 지정할 때 사용됨.
- 즉, try 블록 내에서 예외가 발생하면, C++의 예외처리 메커니즘에 의해서 처리가 된다.
try
{
// 예외발생 예상지역
}
- try 블록을 묶는 기준은 예외가 발생할만한 영역을 묶는 것이 아니다!
- 예외가 발생할만한 영역만 묶는 것이 아니라, 그와 관련된 모든 문장을 함께 묶어서 이를 하나의 ‘일(work)’의 단위로 구성해야된다.
Catch
- Catch 블록은 try블록에서 발생한 예외를 처리하는 코드가 담기는 영역으로써, 그 형태가 마치 반환형이 없는 함수와 유사.
catch(처리할 예외의 종류 명시)
{
// 예외처리 코드의 삽입
}
- catch 블록은 항상 try 블록 뒤에 등장해야함. try 블록에서 발생한 예외는 Catch 블록에서 처리 됨.
try
{
// 예외발생 예상 지역
}
cout<< "Hello world!" <<endl; // 컴파일 error
catch(처리할 예외의 종류 명시)
{
// 예외처리 코드의 삽입
}
throw
- throw는 예외가 발생했음을 알리는 문장의 구성에 사용됨.
- expn은 변수, 상수 그리고 객체 등 표현 가능한 모든 데이터가 될 수 있으나, 예외상황에 대한 정보를 담은, 의미 있는 데이터이어야 함!!
- expn의 위치에 오는 데이터를 가리켜 ‘예외’라고 표현함.
throw expn;
C++ 메커니즘
→ throw에 의해 던져진 ‘예외’ 데이터는 ‘예외’ 데이터를 감싸는 try 블록에 의해서 감지가 되어 이어서 등장하는 catch 블록에 의해 처리됨.
try
{
if(예외가 발생한다면)
throw expn;
}
catch (type expn)
{
// 예외의 처리
}
예제
#include <iostream>
int main()
{
int num1, num2;
std::cin >> num1 >> num2;
try
{
if (num2 == 0)
throw(num2);
}
catch(int num2)
{
std::cout << "제수는 " << num2 << "가 될 수 없습니다.\\n";
}
}
- 두 숫자를 입력하면 두 숫자를 나눠서 몫과 나머지를 출력하는 프로그램.
- 제수가 0일 경우 예외처리.
코드 순서
- num2가 0이 되면 throw를 통해 num2 값이 catch 블록으로 던져진다.
- try 블록 내에서 예외가 발생하면, catch 블록이 실행되고 나서, 예외가 발생한 지점 이후에 실행하는 것이 아니라, catch 블록에서 이루어짐
throw, catch 자료형
→ throw 절에 의해 던져진 ‘예외’ 데이터의 자료형과 catch 블록의 매개변수 자료형은 일치해야한다.
- 만약, 일치하지 않으면, 던져진 ‘예외’ 데이터는 catch 블록으로 전달되지 않는다.
- ‘예외’ 데이터가 catch 블록으로 전달되지 않은 경우
- terminate 함수의 호출로 인해서 프로그램은 종료됨 (주의해서 최대한 예외처리를 하자.)
다중 catch 문
#include <iostream>
#include <string>
int ft_atoi(char *tmp)
{
int count = strlen(tmp);
if (tmp[0] == '0' )
throw(0);
int i = 0;
int num = 0;
while (tmp[i])
{
if (('0' > tmp[i] && tmp[i] > '9'))
throw(tmp[i]);
num += (int)(pow((double)10, (count - 1) - i * tmp[i] - '0'));
i++;
}
return num;
}
int main()
{
char num1[100], num2[100];
std::cin >> num1 >> num2;
try
{
std::cout << num1 << " + " << num2 << ft_atoi(num1) + ft_atoi(num2) << "\\n";
}
catch(int num2)
{
if (!num2)
std::cout << "0으로 시작될 수 없다\\n";
}
catch(char number)
{
std::cout << "숫자가 아니다.\\n";
}
}
- 0으로 시작하는 수의 입력에 정수형 예외에 던져줌.
- 숫자가 아닌 수가 들어오는 char zero 예외 던져줌
→ 함수 내에서 발생할 수 있는 예외의 종류도 함수의 특징으로 간주됨.
이미 정의된 특정 함수의 호출을 위해서는 함수의 이름, 매개변수 선언, 반환형 정보에 더해서, 함수 내에서 전달될 수 있는 예외의 종루(자료형)와 상황도 알아야함.
다중 catch문의 주의점
- catch문은 위에서부터 아래로 내려가면서 ‘예외’ 데이터에 타당한 catch문을 찾는다.
- 만약 유도 클래스의 자료형이 catch문 가장 위에 있고, 아래에 기초 클래스의 자료형이 밑에 있다고 가정하자.
- 기초클래스 자료형은 기초 클래스의 자료형인 catch문에 들어가지 않고 맨 위에 있는 유도 클래스의 자료형인 catch 문에 들어갈게 될 것이다.
- 상속 구조의 클래스 자료형을 둘 이상 catch문에 기입하게 되면 기초 → 유도 순서대로 catch문을 기입하자.
class A
{ ... };
class B : public A
{ ... };
class C : public B
{ ... };
int main()
{
try
{ ... }
catch(C& expn)
{ ... }
catch(B& expn)
{ ... }
catch(A& expn)
{ ... }
}
catch (…)에 대하여
- catch 블럭을 이렇게 선언하면 try 블록 내에서 전달되는 모든 예외가 자료형에 상관없이 걸려듬.
- 마지막 catch 블록에 많이 덧붙여지지만, 발생한 예외에 관련해서 정보를 얻을 수 없다.
try
{
...
}
catch(...)
{
...
}
반응형
'C++ > C++ try catch, throw, what, exception' 카테고리의 다른 글
exception, what (0) | 2024.01.26 |
---|