항목 7. 다형성을 가진 기본클래스에서는 소멸자를 반드시 가상 소멸자로 선언하자
class TimeKeeper {
public:
TimeKeeper ();
~TimeKeeper ();
}
class AtomicClock : public TimeKeeper { ... };
class WaterClock : public TimeKeeper { ... };
class WristClock : public TimeKeeper { ... };
클래스의 혜택을 받는 사용자들은 시간 계산이 어떻게 되는지는 관심이 없고 시간 정보에 접근하고 싶어한다.
객체에 대한 포인터 를 얻기위해 팩토리 함수
를 만들어 놓는다.
TimeKeeper *getTimeKeeper ();
반환되는 객체는 힙 에 있게 되므로 메모리 및 기타 자원의 누수를 막기 위해 객체를 삭제 해야 한다.
객체 삭제를 사용자에게 전가 하는 것은 에러 발생에 노출될 소지가 있다.
팩토리 함수의 인터페이스를 수정 하면 사용자 에러를 방지할 수 있다.
포인터를 통해 날아오는 서브 클래스 객체 (AtomicClock
, WaterClock
, WristClock
)는 기본 클래스 포인터 (TimeKeeper
)를 삭제할때 기본클래스 객체의 소멸자 만 호출되고 서브클래스 객체의 소멸자 는 실행되지 않는다. (부분 소멸)
부분소멸이 일어났으니 자원의 누수가 발생하게 된다.
기본 클래스의 소멸자에 virtual
키워드를 붙여줌으로써 해결할 수 있다.
virtual
키워드를 붙여주면 서브 클래스까지 모두 소멸자가 호출 된다.
가상 함수 를 하나라도 가진 클래스는 가상 소멸자 를 가져야 하는게 대부분 맞다.
객체가 가상 소멸자 를 가지고 있지 않다면 기본 클래스로 사용되지 않을것 이다라고 생각해도 된다.
가상 소멸자 를 선언하는 것은 그 클래스에 가상 함수가 하나라도 들어 있는 경우 로 한정하는것이 좋다.
STL
컨테이너 타입(vector
, list
, set
, unordered_map 등)은 가상 소멸자가 없다.
STL
을 기본 클래스로 잡는 실수를 해서는 안된다.
경우에 따라서 순수 가상 소멸자를 두면 편리하게 사용할 수 있다.
클래스가 추상 클래스(인스턴스를 못 만드는 클래스)였으면 좋겠는데 넣을 만한 순수 가상 함수가 없을때 가 있다.
순수 가상 소멸자를 선언 하는것을 통해 해당 클래스를 추상 클래스로 만들면된다.
단, 순수 가상 소멸자의 정의 를 하여야만 한다.
class AWOV {
public:
virtual ~AWOV () = 0 ; // 순수 가상 소멸자를 선언
}
AWOV::~AWOV () {} // 순수 가상 소멸자의 정의