말그대로 예외 동작이 소멸자 내에서 종료되어야 함을 의미한다.
1. 소멸자가 호출되는경우
(1) 정상적으로 객체가 종료되었을때
(2) 예외처리 메커니즘에 의해 객체가 소멸될때
(2)와 같이 예외처리 메커니즘에 의해 객체가 소멸될때 또 예외가 발생한다면, terminate함수가 호출되어 프로그램이 종료된다. 따라서 try catch로 예외를 소멸자내에서 묶어두어야 한다.
일반적으로 c++은 예외를 내보내는 소멸자를 좋아하지 않는다!!라고 생각하자.
자 우선 이 코드를 봐보자.
class DBConnection {
public :
...
static DBConnection create();
void close();
};
class DBConn {
public :
...
~DBConn()
{
db.close(); //여기서 예외발생시 소멸자에서 예외가 나가도록 내버려둔다.
}
private:
DBConnection db;
};
위 코드에서 DBConn객체에 예외가 발생하여 ~DBConn()호출을 하였고, 여기서 또 예외발생시, 프로그램이 미정의 동작을 발생시킬것이다.
TIP). try catch로 예외를 소멸자에 묶어보자.
해결방법 1. 프로그램을 바로 끝낸다.
DBConn::~DBConn()
{
try{db.close();}
catch(…){
//close 호출이 실패했다는 로그를 작성합니다;
std::abort();
}
}
해결방법 2. 예외를 삼켜버린다.
DBConn::~DBConn()
{
try { db.close(); }
catch(…){
//close 호출이 실패했다는 로그를 작성합니다;
}
}
위 경우는 예외를 삼킨 이후에도 프로그램의 정상동작이 보장되어야 빛을 볼것이다.
해결방법3. 문제 대처기회를 사용자에게 선 제공하자. 책임전가 해버리자.
따라서 예외 발생시 그 예외는 소멸자가 아닌 다른 함수에서 비롯되어야 한다.
예외를 일으키는 소멸자는 시한폭탄이다.!!!
class DBConn{
public :
void close()
{
db.close();
closed = true;
}
~DBConn()
{
if(!closed)
try{
db.close();
}
catch(...){
//close 호출이 실패했습니다. 로그작성
...
}
private:
DBConnection db;
bool closed;
};
이것만은 잊지 말자!
1. 소멸자에서 예외를 묶어두자. 방법은 삼키던가 프로그램 강제종료시키던가
2. 예외가 발생하는 함수는 보통의 함수여야 한다.(소멸자가 아닌 함수)
'책 정리 > Effective C++ 3rd' 카테고리의 다른 글
항목 10. 대입 연산자는 *this의 참조자를 반환하게 하자 (0) | 2019.12.18 |
---|---|
항목 9. 객체 생성 및 소멸 과정 중에는 절대로 가상 함수를 호출하지 말자 (0) | 2019.12.17 |
항목 4. 객체를 사용하기 전에 반드시 그 객체를 초기화하자 (0) | 2019.12.15 |
항목 3. 낌새만 보이면 const를 들이대 보자! (0) | 2019.12.10 |
항목 2. #define을 쓰려거든 const, enum, inline을 떠올리자 (0) | 2019.12.04 |
댓글