C++/C++ try catch, throw, what, exception

Try Catch, throw

재윤 2024. 1. 26. 11:48
반응형

→ 우리에게 익숙한 예외처리는 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일 경우 예외처리.

코드 순서

  1. num2가 0이 되면 throw를 통해 num2 값이 catch 블록으로 던져진다.
    1. 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문의 주의점

  1. catch문은 위에서부터 아래로 내려가면서 ‘예외’ 데이터에 타당한 catch문을 찾는다.
  2. 만약 유도 클래스의 자료형이 catch문 가장 위에 있고, 아래에 기초 클래스의 자료형이 밑에 있다고 가정하자.
  3. 기초클래스 자료형은 기초 클래스의 자료형인 catch문에 들어가지 않고 맨 위에 있는 유도 클래스의 자료형인 catch 문에 들어갈게 될 것이다.
  4. 상속 구조의 클래스 자료형을 둘 이상 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