어떤 함수의 본체 어느 곳에서나 예외가 발생할 수 있다면 이 함수의 본체를 try 블록으로 완전히 묶어 버려야 한다.
즉, 다음과 같이 말이다.
#include <iostream>
void divide(int a, int d)
{
try {
if (d == 0) throw "0으로는 나눌 수 없다.";
std::cout << a / d << std::endl;
}
catch (const char* message) {
std::cerr << message << std::endl;
}
}
int main(void)
{
divide(10, 0);
}
만약 위의 예시처럼 함수의 실질적인 코드 부분이 try 블록에 작성되어 있다면 다음과 같이도 표기할 수 있다.
#include <iostream>
void divide(int a, int d)
try {
if (d == 0) throw "0으로는 나눌 수 없다.";
std::cout << a / d << std::endl;
}
catch (const char* message) {
std::cerr << message << std::endl;
}
int main(void)
{
divide(10, 0);
}
뭔가 모양이 많이 다르다.
하지만 이것이 필요한 이유는 멤버에 대한 초기화를 진행할 때 즉, 멤버 초기화 리스트에서 에러가 발생할 때 생성자 자체를 try 블록 함수로 만들 수 있다.
#include <iostream>
class Value
{
private:
int x;
public:
Value(int ax)
try : x(ax) {
if (ax < 0) throw ax;
}
catch (int a) {
std::cerr << ax << "는 음수입니다." << std::endl;
}
};
int main(void)
{
try {
Value X(-1);
}
catch (int) {
std::cerr << "무효함" << std::endl;
}
return 0;
}
이렇게 하여 초기화 리스트까지 예외 처리 블록에 포함시킬 수 있게 된다.
생성자에서 객체 생성 조건이 맞지 않을 경우의 예외를 처리하더라도 이 예외는 자동으로 다시 던져지도록 되어 있다. 왜냐하면 객체 생성 단계의 예외는 객체 혼자만의 문제가 아니라 객체를 선언한 곳과도 관련이 있기 때문이다.
만약 이 처리(예제에서는 메인 함수에서 한 처리)를 하지 않으면 프로그램이 다운된다.