소멸자에서 예외 처리를 해야 하는 상황
결론부터 봤을 때, 소멸자에서 예외를 던지는 것은 좋지 않다고 합니다.
class DBConnection
{
public:
...
static DBConnection create(); // 자신의 객체를 반환. 매개변수 생략
void close(); // 연결을 닫고, 실패하면 예외를 던지는 코드가 있다고 가정
};
// DBConnection 객체를 관리하는 클래스
class DBConn
{
pubilc:
...
~DBConn()
{
m_db.close(); // 소멸자를 통해 연결이 항상 닫히도록 한다.
}
private:
class DBConnection m_db;
};
{
// 블록 시작
DBConn dbc(DBConnection::create());
...
// 블록 종료
// dbc 객체 소멸자 호출(DBConnection::close 호출)
}
위에 있는 dbc 객체는 함수를 빠져나올 때 소멸자를 호출할 것입니다.
그래서 DBConnection의 close 함수를 호출하면서 예외를 던질 수 있습니다.
하지만 소멸자에서 예외를 던지면 미정의 동작으로 빠질 수도 있습니다.
이럴 땐 차라리 소멸자에서 프로그램을 강제로 종료하거나 예외를 삼켜버리라고 합니다.
프로그램이 그대로 미정의 동작으로 흐르는 것보다 나을 수 있기 때문입니다.
// 소멸자에서 프로그램 종료
// 소멸자에서 에러 발생 후 프로그램을 계속 실행할 수 없는 상황에서 괜찮은 선택이 될 수도 있다.
DBConn::~DBConn()
{
try(m_db.close())
{
...
}
catch(...)
{
close 호출 실패 로그 출력
// 프로그램 종료
// 예외를 밖으로 던지지 않고 미정의 동작이 발생할 수 있는 것을 미리 막는다.
std::abort();
}
};
// 소멸자에서 예외 삼켜버리기
// 어떻게든 소멸자에서 예외를 삼켜버린다.
// 그러나 이렇게 할 경우 무엇이 잘못됐는지 정확한 정보가 없기 때문에 좋은 방법은 아니다.
// 예외 삼키기는 예외를 무시한 뒤라도 프로그램의 실행이 지속되어야한다는 신뢰성이 있어야 한다.
CDBConn::~CDBConn
{
try(m_db.close())
{
...
}
catch(...)
{
close 호출 실패 로그 출력
}
};
close 함수가 최초로 예외를 던질 때, 이에 대한 대책이 없어서
어느쪽을 택하든 좋은 쪽이 없어보입니다.
단지, 두 방법의 공통적인 의도는 어떻게든 소멸자 내에서
예외가 빠지나가지 않도록 막는 것입니다.
예외가 발생할 수 있는 함수는 따로 정의한다
예외는 소멸자가 아닌, 프로그램이 실행중인 함수에서 비롯되어야 합니다.
그래서 예외가 발생할 수 있는 함수를 사용자가 미리 정의해둡니다.
class DBConn
{
pubilc:
// 예외를 던질 수 있는 함수(db.close)를
// 사용자가 직접 호출할 수 있도록 정의한다.
void close()
{
db.close();
closed = true;
}
DBConn() :
m_bIsClose(false)
{...}
~DBConn()
{
// 사용자가 연결을 닫지 않았으면 소멸자에서 시도해본다.
// 실패하면 실행을 끝내거나 예외를 삼킨다.
if(!m_bIsClose)
{
try{m_db.close()}
catch(...)
{
close 호출 실패 로그 출력
}
}
}
private:
class DBConnection m_db;
bool m_bIsClose;
};
이제 close 함수를 소멸자가 아닌 사용자가 원하는 시점에 처리하면
예외를 능동적으로 처리할 수 있게 됩니다.
소멸자에서 프로그램을 종료시키거나 예외를 삼켜버리는 방법은 최후의 보루로 남겨둡니다.
'Effective C++ 정리' 카테고리의 다른 글
10. 대입 연산자는 *this의 참조자를 리턴한다 (0) | 2020.01.04 |
---|---|
09. 생성자, 소멸자에서 가상 함수를 호출하지 않는다. (0) | 2020.01.04 |
07. 다형성을 가진 기본 클래스 소멸자는 반드시 가상 소멸자로 선언하자 (0) | 2019.12.29 |
06. 컴파일러가 자동으로 생성하는 함수 호출 없애기 (0) | 2019.12.20 |
05. 컴파일러가 자동으로 생성하는 함수 (0) | 2019.12.20 |