throw
문을 가지고 있는 함수는 함수 선언문에 예외 발생을 명시할 수 있다. 그 형식은 함수에서 발생시키는 모든 예외 타입을 함수 원형 뒤에 throw()
의 괄호 안에 나열한다.
예를 들면, int 타입
과 char* 타입
의 예외를 던질 수 있도록 작성된 foo() 함수는 다음과 같이 선언한다.
double foo(double* p, int index) throw(int, char*)
{
if(index < 0)
throw "index out of bounds exception."; // char* 타입 예외 발생
else if(p == nullptr)
throw 0; // int 타입 예외 발생
return p[index];
}
이런 식으로 함수를 선언하는 것이 의무 사항은 아니지만 다음과 같은 장점이 있다.
컴파일러는 함수 선언문의 throw()
에 선언되지 않은 예외가 발생하면 프로그램을 중지시키도록 컴파일한다. 그러나 컴파일러에 따라서는 그냥 넘어가기도 한다.
원형만 봐도 함수에서 발생시키는 예외를 알 수 있어, 코드를 쉽게 이해할 수 있다.
어떤 예외라도 포착하는 catch() 블록
catch의
( )
안에 예외 파라미터 대신 생략 부호(...) 를 주면, 어떤 예외라도 포착할 수 있다. 그러나catch(...) { }
블록은 반드시 마지막catch( )
로만 사용해야 한다. 예를 들면 다음과 같다.
try
{
thow ...;
}
catch(int x) { 예외처리코드 } // int 타입의 예외 처리
catch(...) { 예외처리코드 } // 그 밖의 모든 예외 처리. 반드시 마지막 catch()로만 사용.
다음은 예외처리를 가진 스택 클래스의 예이다.
#include <iostream>
using namespace std;
class MyStack
{
public:
MyStack() { tos = -1; }
void push(int n) throw(char*)
{
if (tos == 99)
{
throw "Stack Overflow";
}
tos++;
data[tos] = n;
}
int pop() throw(char*)
{
if (tos == -1)
{
throw "Stack Empty";
}
int rData = data[tos--];
return rData;
}
private:
int data[100];
int tos;
};
int main()
{
MyStack intStack;
try
{
intStack.push(100);
intStack.push(200);
cout << intStack.pop() << endl;
cout << intStack.pop() << endl;
cout << intStack.pop() << endl;
}
catch (const char* e)
{
cout<< "Exception: " << e << endl;
}
catch (...)
{
cout << "Unknown exception occurred." << endl;
}
return 0;
}
// 결과
200
100
Exception: Stack Empty