결론을 먼저 얘기하면 다음과 같다.
클래스가 상속되어 사용될 가능성이 있는 경우,
특히 부모 클래스의 포인터로 자식 클래스를 핸들링하는 경우
반드시 소멸자를 가상함수로 선언해야 한다.

백문이 불여일견.
다음의 예를 보자.

Main.h
#include <stdio.h>
class CBase
{
public:
 CBase()
 {
  printf("[CBase::CBase] 부모의 생성자\n");
 }
 ~CBase()
 {
  printf("[CBase::~CBase] 부모의 소멸자\n");
 }
};

class CChild : public CBase
{
public:
 CChild()
 {
  printf("[CChild::CChild] 자식의 생성자\n");
 }
 ~CChild()
 {
  printf("[CChild::~CChild] 자식의 소멸자\n");
 }
};

Main.cpp
#include "Main.h"
int main()
{
 CChild* lpChild;
 
 lpChild = new CChild;
 delete lpChild;
 return 0;
}
 


이 코드의 결과는 실행 결과는 다음과 같다.

[CBase::CBase] 부모의 생성자
[CChild::CChild] 자식의 생성자
[CChild::~CChild] 자식의 소멸자
[CBase::~CBase] 부모의 소멸자
Press any key to continue


모.. 여기까지는 아주 정상적으로 예상했던 바다.

그렇다면... 파생 클래스를 베이스 클래스의 포인터를 사용하여 핸들링하면 어떻게 될까?

#include "Main.h"

int main()
{
 CBase* lpBase;
 
 lpBase = new CChild;

 delete lpBase;

 return 0;
}


여기서 문제가 발생한다.

[CBase::CBase] 부모의 생성자
[CChild::CChild] 자식의 생성자
[CBase::~CBase] 부모의 소멸자
Press any key to continue

자식 클래스의 소멸자가 호출되지 않았다.
만약 자식 클래스의 소멸자에 메모리를 해제하는 코드가 들어있었다면? 이것은 Memory Leak으로 연결되었을 것이다.

클래스를 선언한 Main.h를 다음과 같이 수정해보자.

#include <Windows.h>
#include <stdio.h>

class CBase
{
public:
 CBase()
 {
  printf("[CBase::CBase] 부모의 생성자\n");
 }
 virtual ~CBase()    // 여기를 가상함수로 수정!!
 {
  printf("[CBase::~CBase] 부모의 소멸자\n");
 }
};


class CChild : public CBase
{
public:
 CChild()
 {
  printf("[CChild::CChild] 자식의 생성자\n");
 }
 ~CChild()
 {
  printf("[CChild::~CChild] 자식의 소멸자\n");
 }

};

수정 결과는 다음과 같다.

[CBase::CBase] 부모의 생성자
[CChild::CChild] 자식의 생성자
[CChild::~CChild] 자식의 소멸자
[CBase::~CBase] 부모의 소멸자
Press any key to continue


잘 되었다.
이래서~~ 소멸자는 가상함수어야 한다는 거다.

 

Posted by kuaaan
,


사랑합니다. 편안히 잠드소서