2009. 1. 22. 13:49

발생한 예외는 참조자로 받아내자

예외 객체가 전달되는 방식을 설정하는 방법은 3가지가 있다

 

1.      포인터

2.     

3.      참조자

 

비록 이렇게 3가지라고 하나 예외는 무조건 참조자로 받아야만 한다. 그 이유를 살펴보자.

 

1.      포인터

void someFunction()

{

exception ex;

throw &ex;           // ex 객체는 유효범위를 벗어나면 소멸됨

}

 

void doSomething()

{

try {

someFunction();

}

Catch(exception * ex)         // 소멸된 예외 객체를 가리킴

}

}

 

만약 new로 할당하여 예외 객체를 던지게 되면 예외 객체의 소멸 문제가 남아 있으며, 해당 예외가 new로 할당한 것인지 아님 전역 객체인지를 구분할 수 있는 방법이 없음.

 

2.     

l       Slicing Problem (잘림)

class exception {

virtual const char * what() throw();

}

 

class runtime_error : public exception { … };

class validation_error : public exception { … };

 

void someFunction () {

throw validation_error();

}

 

void doSomething() {

try {

someFunction();

}

catch(exception ex) {

             cerr << ex.what();

}

}

 

발생한 예외가 validation_error 타입이고, validation_error에서 가상함수 what을 재정의하였다고 해도, 호출되는 what은 기본클래스인 exception what이 된다.

 

3.      참조자

참조자에 의한 예외받기는 두 방법이 가지고 있는 문제를 겪지 않는다. “포인터에 의한 예외받기와 달리, 객체 삭제에 대한 고민도 할 필요 없고, C++ 표준 예외를 처리하는 데에도 무리가 없슴. 그뿐 아니라, “값에 의한 예외받기와 달리 슬라이스 문제도 없고 예외 객체는 한 번만 복사된다. (값에 의한 예외 받기는 두번 복사되는데 이에 대한 자세한 내용은 More Effective C++ 항목 12 참고)

 

참고 : More Effective C++ - 스캇 마이어스 저