본문 바로가기
Programming/Effective C++ 3판

항목 8. 예외가 소멸자를 떠나지 못하도록 붙들여 놓자.

by deviAk 2008. 7. 10.
반응형
class DBConnection {
public:
  static DBConnection create();
  void close();};

위의 DBConnection 객체에 대해 사용자가 cloase를 직접 호출해야 하는 설계이다. 사용자의 망각을 사전에 차단하는 좋은 방법이라면 DBConnection에 대한 자원관리 클래스를 만들어서 그 클래스의 소멸자에서 close를 호출하게 만드는 것이다.
class DBConn {
      // DBConnection 객체를 관리하는 클래스
public:
 ...
 ~DBConn()        // 데이터베이스 연결이 항상 닫히도록 확실히 챙겨주는 함수
 {
  db.cloase();
 }
private:
 DBConnection db;
};

위의 두 클래스를 활용하여 다음과 같은 프로그래밍이 가능해진다.
{                    // 블록 시작
 DBConn dbc(DBConnection::create());  // DBConneciton 객체를 생성하고
                                         // 이것을 DBConn 객체로
                    // 넘겨서 관리를 맡긴다.
 ...   // DBConn 인터페이스를 통해 DBConnection 객체를 사용한다.
}     // 블록 끝. DBConn 객체가 여기서 소멸된다. 
      // 따라서 dBConnection 객체에 대한 close 함수의 호출이
           // 자동으로 이루어진다.

close 호출만 일사천리로 성공하면 아무 문제될 것이 없는 코드 이지만 만약 close 호출햇는데 여기서 예외가 발생했다고 가정하면 DBConn의 소멸자는 분명히 이 예외를 전파할 것이다.

class DBConn {
public:
 ...
 void close()
 {
  db.close();
  closed = true;
 }
 ~DBConn()
 {
  if (!closed)
  try {
   db.close();
  }
  catch (...) {
   close 호출이 실패 했다는 로그를 작성한다.
   ...
  }
 }
private:
 DBConnection db;
 bool closed;
};


어떤 동작이 예외를 일으키면서 실패할 가능성이 있고 또 그 예외를 처리해야 할 필요가 있다면, 그 예외는 소멸자가 아닌 다른 함수에서 비롯된 것이어야 한다는 것이 포인트 이다.


이것만은 잊지 말자!
- 소멸자에서는 예외가 빠져나가면 안된다. 만약 소멸자 안에서 호출된 함수가 예외를 던질 가능성이 있다면, 어떤 예외든지 소멸자에서 모두 받아낸 후에 삼켜버리든지 프로그램을 끝내든지 해야 한다.,

- 어떤 클래스의 연산이 진행되다가 던진 예외에 대해 사용자가 반응해야 할 필요가 있다면, 해당 연산을 제공하는 함수는 반드시 보통의 함수),즉 소멸자가 아닌 함수)이어야 한다.

관련 링크
http://ikpil.tistory.com/409
http://ikpil.tistory.com/365
http://redinlife.egloos.com/1627105
http://ilu8318.egloos.com/1705005
http://flashcafe.org/bbs/board.php?bo_table=programming_study&wr_id=83
반응형