class TimeKeeper{
public:
TimeKeeper();
~TimeKeeper();
...
};
class AtomicClock:public TimeKeeper{...};
class WaterClock:public TimeKeeper{...};
class WristWatch:public TimeKeeper{...};
* 팩토리 함수(Factory Function, 새로 생성된 파생 클래스 객체에 대한 기본 클래스 포인터를 반환하는 함수)
TimeKeeper* ptk = getTimeKeeper();
...
delete ptk;
여기서 getTimeKeeper()가 AtomicClock 객체에 대한 포인터를 반환한다고 했을 때, 해당 객체는 동적 생성이므로 힙(heap)에 위치하게 된다. 객체가 삭제될 때 TimeKeeper*를 통해 삭제되게 되는데, 문제는 이때 발생한다. TimeKeeper 클래스의 소멸자가 비가상 소멸자이기 때문이다.
C++의 경우, 기본 클래스 포인터를 통해 파생 클래스 객체가 삭제될 경우 그 기본 클래스에 비가상 소멸자가 들어 있으면 프로그램 동작은 미정의 사항이라고 규정되어 있다. (어찌될지 모른다고~) 그리고 대개 그 객체의 파생 클래스 부분이 소멸되지 않게 된다.
이 문제를 해결하기 위해서는 위의 TimeKeeper 클래스에서 소멸자를 가상 소멸자로 바꾸면 된다.
class TimeKeeper{
public:
TimeKeeper();
virtual ~TimeKeeper();
...
};
TimeKeeper* ptk = getTimeKeeper();
...
delete ptk;
이렇게 수정을 하게 되면 파생 클래스 객체의 소멸자까지 호출되어 모두 소멸되게 된다. 소멸자의 호출 순서는 파생 클래스의 소멸자가 먼저 호출되며 기본 클래스 쪽으로 거쳐 올라오면서 각 기본 클래스의 소멸자가 호출된다.
그리고 추가적으로 가상 함수를 하나라도 가진 클래스의 경우 대개 가상 소멸자를 가져야 한다.
즉, 다형성을 가진 기본 클래스에는 반드시 가상 소멸자를 선언해야하며, 다시말하면 어떤 클래스가 가상 함수를 가지고 있으면 이 클래스의 소멸자도 가상 소멸자이어야 한다. 반대로 말하면 기본 클래스로 설계되지 않았거나 다형성을 갖도록 설계되지 않은 클래스에는 가상 소멸자를 선언하지 말아야 한다.
'old drawer > C, C++, MFC' 카테고리의 다른 글
[C/C++] 중구난방 스터디 요약 (0) | 2013.12.12 |
---|---|
[Effective C++ 요약] 11. operator=에서는 자기대입에 대한 처리가 빠지지 않도록 하자. (0) | 2013.12.12 |
[C/C++] #ifdef, #ifndef 전처리기 사용법 (1) | 2013.09.09 |
[C/C++] INI 함수 클래스 (0) | 2013.08.06 |
[MFC] File Operations Source (0) | 2013.08.06 |